我一直在VS2012教自己C ++,并且遇到了一些真正让我摸不着头脑的东西。当创建一个对象并在另一个对象中添加对它的引用时,该对象似乎被破坏或者某些东西。它是不 null(空指针检查的每个组合我可以确认这一点),但其内容很时髦并且试图访问其中一个成员导致“0xC0000005:访问冲突读取位置0xCCCCCCE8”。 / p>
我的程序的要点是我有一个Tile对象的2D向量,每个对象都可以引用一个站点。当我在具有网站的tile的draw()函数中时,它将尝试以其文明所属的颜色绘制该网站。
世界一代:
std::vector<std::vector<Tile>> world;
// ... vector is sized ...
// Populate world with tiles
for (int h=0; h<height; h++) {
for (int w=0; w<width; w++) {
Tile t(PLAINS);
world[h][w] = t;
}
}
创建文明时,会为它们创建一个简单的大写网站,并将其引用放在指定x,y的区块中:
void Game::createCivilisation(std::string name, sf::Color colour, int x, int y) {
// Create the civ
Civilisation civ(name, colour);
// Create their capital and link it up
Site capital("Capital", year, &civ); // when I comment these five lines out
civ.capital = &capital; // the program doesn't crash, so I know
civ.sites.push_back(capital); // that the dodgy site originates here.
// Add capital to tile
world[y][x].site = &capital;
capital.location = &world[y][x];
}
当调用Tile的draw()函数时,它会在尝试访问该站点的成员时死亡。这只是一个文明。
if (site != nullptr) { // have also tried (site) (site!=0) (site!=NULL)
sf::CircleShape s(tileWidth*0.5);
s.setFillColor(site->civilisation->colour); // womp womp
上图是提供的调试信息。如你所见,这都是垃圾。 “资本”已成为几十亿字符串的垃圾,一切都是错误的,所有对其他对象的引用也都消失了。当我评论出资本网站链接时
我想我已经提供了所有相关的代码片段(为了简洁起见/为了她的乐趣)。我已经在这个工作了几个小时,它让我难过。所有索引都应该是正确的,createCivilisation()中生成的网站绝对是唯一存在的网站等等。
答案 0 :(得分:6)
这是错误的
Site capital("Capital", year, &civ); // when I comment these three lines out
civ.capital = &capital; // the program doesn't crash, so I know
civ.sites.push_back(capital); // that the dodgy site originates here.
// Add capital to tile
world[y][x].site = &capital;
您正在将指针&capital
存储到本地对象(并且看起来要做两次)。当你的createCivilisation
方法退出时,本地对象被销毁,所以你最终得到垃圾指针。
简单的答案是复制对象本身而不是尝试存储指针。如果对象很大并因此复制它们是一个问题,那么您应该查看动态堆分配和智能指针。
答案 1 :(得分:4)
在调试模式下运行时,Visual Studio会自动使用0xCCCCCCCC填充已释放(或超出范围)的内存。这使您可以捕获免费使用后的错误,例如您刚刚遇到的错误。
您正在创建对局部变量(堆栈变量)的引用。该变量在方法结束时超出范围,在world
中留下悬空指针。
您可能希望在堆上分配对象:
Site *capital = new Site("Capital", year, &civ);
虽然您必须弄清楚何时释放capital
以避免内存泄漏。您还可以使用智能指针(在本例中为shared_ptr
或类似)来简化您的生活。