C++ 程序中的异常行为,经常崩溃

Unusual behavior in c++ program, crashing often

我最近在我的程序中遇到了一个问题,似乎也没有人遇到过这个问题,我已经在互联网上搜索了解决方案,但我找不到,让我解释一下。

问题

我从事 2D 平台游戏已有一段时间了,并且正在慢慢实现新功能,但是,我遇到了障碍。我目前正在为碰撞和物理目的将 AABB 树实现编程到我的游戏中,它似乎造成了很多麻烦。我最终修复了程序中的所有错误并得到了一个有效的实现,至少,我认为我做到了,直到随机错误开始出现。令我惊讶的是,它实际上根本不是我的 AABB class,而是这个单一的代码块。

while (fs.tellg() < Size) {
    unsigned short int x, y, w, h;
    fs.read(reinterpret_cast<char *>(&x), 2);//I'm reading from a binary
    fs.read(reinterpret_cast<char *>(&y), 2);//file containing the AABB
    fs.read(reinterpret_cast<char *>(&w), 2);//rectangle points
    fs.read(reinterpret_cast<char *>(&h), 2);// x,y, width,height

    //These are the two lines where the error occurs
    unsigned nodeNum = tree.allocateNode(x*35, y*35, w*35, h*35);
    tree.insertLeaf(nodeNum); //Here is where it crashes                                   

};

但是别着急,这还不是全部...


奇怪的部分

当我诊断出这个错误时,我遇到了一些有趣的事情。

1. 该程序实际上 运行 完全是一小部分时间。我设置 在命令末尾添加 system("pause"); 以查看它是否会 运行 确实如此!在我按回车键过去之后它也立即崩溃了 暂停块。

2. 由于某些原因,这很好用

unsigned nodeNum = tree.allocateNode();
tree.insertLeaf(nodeNum);

unsigned nodeNum2 = tree.allocateNode();
unsigned nodeNum3 = tree.allocateNode();

tree.insertLeaf(nodeNum3);
tree.insertLeaf(nodeNum2);

但是这根本不起作用,它实际上使程序崩溃。

unsigned nodeNum = yahh.allocateNode();
tree.insertLeaf(nodeNum);

unsigned nodeNum2 = yahh.allocateNode();
tree.insertLeaf(nodeNum2);

unsigned nodeNum3 = yahh.allocateNode();
tree.insertLeaf(nodeNum3);

这也行。

unsigned nodeNum2 = tree.allocateNode();
tree.insertLeaf(nodeNum2);

unsigned nodeNum2 = tree.allocateNode();
//tree.insertLeaf(nodeNum2);

但这不是。好像调用 allocateNode();insetLeaf(); 命令两次以使程序崩溃...

unsigned nodeNum2 = tree.allocateNode();
tree.insertLeaf(nodeNum2);

unsigned nodeNum2 = tree.allocateNode();
tree.insertLeaf(nodeNum2);

源代码

AABBtree.h

#define AABB_NULL_NODE 0xffffffff

struct AABBNode {
    unsigned nodeNum;
    //AABBNode(unsigned _newNode) : _newNode(nodeNum) { };
    ~AABBNode(){ };
};
//==========================================================================
//==========================================================================
class AABBtree {
private:
    unsigned _rootNode = AABB_NULL_NODE;
    std::vector<AABBNode> _nodeTable;
public:
    AABBtree() { };
    ~AABBtree(){ };

    unsigned allocateNode() {
        //Allocate node and return new Node index
        unsigned nodeNum = _nodeTable.size();
        _nodeTable.emplace_back(nodeNum);
        return nodeNum;
    };

    void insertLeaf(unsigned& nodeNum) {
        AABBNode& newNode = _nodeTable[nodeNum];

        //Allocate a new AABB, it will be curNode and newNode new parent.
        unsigned newParentIndex = allocateNode();
        AABBNode& newParent = _nodeTable[newParentIndex];
    };
};

Main.cpp

AABBtree tree;
int main() {
    unsigned nodeNum = tree.allocateNode();
    tree.insertLeaf(nodeNum);
    unsigned nodeNum2 = tree.allocateNode();
    tree.insertLeaf(nodeNum2);
};

我已经将大部分部分剪掉到最低限度

我认为问题与您的 insertLeaf 方法有关。

void insertLeaf(unsigned& nodeNum) {
    AABBNode& newNode = _nodeTable[nodeNum];

    //Allocate a new AABB, it will be curNode and newNode new parent.
    unsigned newParentIndex = allocateNode();
    AABBNode& newParent = _nodeTable[newParentIndex];
}

此方法首先获取对 vector (_nodeTable) 内对象的引用。

接下来它调用 allocateNode()。在 allocateNode 方法中,它在向量上调用 emplace_back,这可能会增加 _nodeTable.

的大小

这就是问题所在 - 如果矢量由于达到其容量而必须调整大小,那么您丢失了调用 allocateNode 之前的引用。您现在拥有所谓的 悬空引用 ,即未绑定到内存中的对象的引用。

如果 _nodeTable 在调用 emplace_back 后调整大小,然后回到您的 insertLeaf 方法,您现在有一个无效的节点引用。

快速修复