1

我遇到了一个严重的错误。当我在对象层次结构顶部的对象上调用 delete 时(希望导致其子对象的删除),我的程序退出,我得到了这个:

*** 检测到 glibc *** /home/mossen/workspace/abbot/Debug/abbot: double free or corruption (out): 0xb7ec2158 ***

其次是看起来像是某种内存转储的东西。我已经搜索过这个错误,从我收集的信息来看,它似乎是在您尝试删除已删除的内存时发生的。不可能,因为我的代码中只有一个地方尝试删除。这是古怪的部分:它不会在调试模式下发生。有问题的代码:


Terrain::~Terrain()
{
    if (heightmap != NULL) // 'heightmap' is a Heightmap*
    {
        cout << "heightmap& == " << heightmap << endl;
        delete heightmap;
    }
}

我已经注释掉了高度图析构函数中的所有内容,但仍然是这个错误。当错误发生时,

高度图& == 0xb7ec2158

被打印。在调试模式下,我可以慢慢地单步执行代码

高度图& == 0x00000000

已打印,并且没有错误。如果我注释掉“删除高度图;” 行,永远不会发生错误。上面的析构函数是从另一个析构函数调用的(单独的类,没有虚拟析构函数或类似的东西)。高度图指针在这样的方法中是新的:


Heightmap* HeightmapLoader::load() // a static method
{
   // ....
   Heightmap* heightmap = new Heightmap();
   // ....other code
   return heightmap;
}

这可能与返回在静态方法的堆栈空间中初始化的指针有关吗?我正确地删除了吗?关于我可以检查或做得更好的任何其他提示?

4

4 回答 4

2

如果load()从不调用会发生什么?您的类构造函数heightmap是初始化,还是在到达析构函数时未初始化?

另外,你说:

...删除已被删除的内存。不可能,因为我的代码中只有一个地方尝试删除。

但是,您没有考虑到您的析构函数可能在程序执行期间被多次调用。

于 2009-10-26T04:43:03.363 回答
2

在调试模式下,指针通常设置为 NULL 并且内存块清零。这就是您在调试/发布模式下遇到不同行为的原因。

我建议您使用智能指针而不是传统指针

auto_ptr<Heightmap> HeightmapLoader::load() // a static method
{
   // ....
   auto_ptr<Heightmap> heightmap( new Heightmap() );
   // ....other code
   return heightmap;
}

这样你以后不需要删除它,因为它会自动为你完成

参见boost::shared_ptr

于 2009-10-26T04:45:56.307 回答
1

您很可能两次调用该 dtor。在调试模式下,指针恰好在删除时归零,在优化模式下,它会被单独放置。虽然不是一个干净的解决方案,但想到的第一个解决方法是heightmap = NULL;在删除后立即设置——它不应该是必要的,但在你寻找为什么要销毁某些 Terrain 实例的解释时肯定不会受到伤害两次!-) [[在您展示的少量代码中绝对没有任何内容可以帮助我们解释双重破坏的原因。]]

于 2009-10-26T04:45:09.520 回答
0

它看起来像未初始化指针的经典案例。正如@Greg 所说,如果没有从地形调用 load() 怎么办?我认为您没有在构造函数中初始化HeightMap*指针。Terrain在调试模式下,此指针可能设置为 NULL,C++ 保证删除 NULL 指针是有效操作,因此代码不会崩溃。但是,由于优化,在释放模式下,指针未初始化并且您尝试释放一些随机内存块,并发生上述崩溃。

于 2009-10-26T04:50:30.150 回答