代码之家  ›  专栏  ›  技术社区  ›  Waneden

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

  •  2
  • Waneden  · 技术社区  · 6 年前

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

    问题

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

    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. 该程序实际上在很小的一部分时间内运行良好。我设置 向上a system("pause"); 在命令末尾查看是否将运行 它做到了!当我按enter键通过 暂停块。

    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];
        };
    };
    

    主要的cpp公司

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

    我把大部分零件都剪到了最低限度

    1 回复  |  直到 6 年前
        1
  •  4
  •   smac89    6 年前

    我认为问题与你的 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];
    }
    

    此方法首先获取对向量内对象的引用( _nodeTable ).

    接下来,它会呼叫 allocateNode() . 在 allocateNode 方法,它调用 emplace_back 可能会增加 _节点表 .


    这就是问题所在-如果向量在达到其容量后必须重新调整大小,那么您就丢失了调用之前的引用 分配节点 . 你现在有了 悬挂引用 i、 e.未绑定到内存中对象的引用。

    如果 _节点表 调用后调整大小 向后安放 ,然后返回 插入式叶 方法,您现在有一个无效的节点引用。

    快速修复