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
方法,您现在有一个无效的节点引用。
快速修复
- 强制向量在获取该引用之前保留足够的内存。您可以使用
std::vector::capacity
method in addition to std::vector::reserve
.
我最近在我的程序中遇到了一个问题,似乎也没有人遇到过这个问题,我已经在互联网上搜索了解决方案,但我找不到,让我解释一下。
问题
我从事 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
方法,您现在有一个无效的节点引用。
快速修复
- 强制向量在获取该引用之前保留足够的内存。您可以使用
std::vector::capacity
method in addition tostd::vector::reserve
.