关于 C++ 的问题内存分配和删除

发布于 2024-08-08 17:20:18 字数 1077 浏览 3 评论 0原文

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

*** glibc detected *** /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;
    }
}

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

heightmap& == 0xb7ec2158

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

heightmap& == 0x00000000

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


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

这是否与返回在静态方法的堆栈空间中初始化的指针有关?我的删除操作正确吗?关于我可以检查什么或做得更好的其他建议吗?

I'm getting a bad error. When I call delete on an object at the top of an object hierarchy (hoping to the cause the deletion of its child objects), my progam quits and I get this:

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

followed by what looks like a memory dump of some kind. I've searched for this error and from what I gather it seems to occur when you attempt to delete memory that has already been deleted. Impossible as there's only one place in my code that attempts this delete. Here's the wacky part: it does not occur in debug mode. The code in question:


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

I have commented out everything in the heightmap destructor, and still this error. When the error occurs,

heightmap& == 0xb7ec2158

is printed. In debug mode I can step through the code slowly and

heightmap& == 0x00000000

is printed, and there is no error. If I comment out the 'delete heightmap;' line, error never occurs. The destructor above is called from another destructor (separate classes, no virtual destructors or anything like that). The heightmap pointer is new'd in a method like this:


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

Could it be something to do with returning a pointer that was initialized in the stack space of a static method? Am I doing the delete correctly? Any other tips on what I could check for or do better?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

情未る 2024-08-15 17:20:18

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

另外,你说:

...删除已经删除的内存。不可能,因为我的代码中只有一个位置尝试进行此删除。

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

What happens if load() is never called? Does your class constructor initialise heightmap, or is it uninitialised when it gets to the destructor?

Also, you say:

... delete memory that has already been deleted. Impossible as there's only one place in my code that attempts this delete.

However, you haven't taken into consideration that your destructor might be called more than once during the execution of your program.

墨落成白 2024-08-15 17:20:18

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

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

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

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

另请参阅 boost::shared_ptr

In debug mode pointers are often set to NULL and memory blocks zeroed out. That is the reason why you are experiencing different behavior in debug/release mode.

I would suggest you use a smart pointer instead of a traditional pointer

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

that way you don't need to delete it later as it will be done for you automatically

see also boost::shared_ptr

月寒剑心 2024-08-15 17:20:18

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

It's quite possible that you're calling that dtor twice; in debug mode the pointer happens to be zeroed on delete, in optimized mode it's left alone. While not a clean resolution, the first workaround that comes to mind is setting heightmap = NULL; right after the delete -- it shouldn't be necessary but surely can't hurt while you're looking for the explanation of why you're destroying some Terrain instance twice!-) [[there's absolutely nothing in the tiny amount of code you're showing that can help us explain the reason for the double-destruction.]]

因为看清所以看轻 2024-08-15 17:20:18

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

It looks like the classic case of uninitialized pointer. As @Greg said, what if load() is not called from Terrain? I think you are not initializing the HeightMap* pointer inside the Terrain constructor. In debug mode, this pointer may be set to NULL and C++ gurantees that deleting a NULL pointer is a valid operation and hence the code doesn't crash. However, in release mode due to optimizations, the pointer in uninitialized and you try to free some random block of memory and the above crash occurs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文