5

我一直在 VS2012 中自学 C++,并且遇到了一些真正让我摸不着头脑的东西。当创建一个对象并在另一个对象中添加对它的引用时,该对象似乎被损坏了。它不是空的(我可以进行的空指针检查的每个组合都证实了这一点),但它的内容很时髦,并且试图访问它的一个成员会导致“0xC0000005:访问冲突读取位置 0xCCCCCCE8”。

在此处输入图像描述

我的程序的要点是我有一个 Tile 对象的 2D 矢量,每个对象都可能引用一个站点。当我在具有站点的图块的 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() 中生成的站点绝对是唯一存在的站点,等等...

4

2 回答 2

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方法退出时,本地对象被销毁,因此您最终得到指向垃圾的指针。

简单的答案是让您复制对象本身,而不是尝试存储指针。如果对象很大,因此复制它们是一个问题,您应该考虑动态堆分配智能指针

于 2013-09-22T07:07:10.063 回答
4

在调试模式下运行时,Visual Studio 会自动使用 0xCCCCCCCC 填充已释放(或超出范围)的内存。这使您能够捕获释放后使用的错误,就像您刚刚遇到的错误一样。

您正在创建对局部变量(堆栈变量)的引用。变量在方法结束时超出范围,在world.

您可能希望在堆上分配对象:

Site *capital = new Site("Capital", year, &civ);

尽管您必须弄清楚何时释放capital以避免内存泄漏。您还可以使用智能指针(在本例中为 ashared_ptr或类似指针)来简化您的生活。

于 2013-09-22T07:14:46.910 回答