简体   繁体   English

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

[英]Questions about C++ memory allocation and delete

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: 当我在对象层次结构顶部的某个对象上调用delete(希望删除其子对象的原因)时,我的程序退出了,我得到了以下信息:

*** 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? 关于我可以检查或做得更好的任何其他提示?

What happens if load() is never called? 如果从不调用load()会发生什么? Does your class constructor initialise heightmap , or is it uninitialised when it gets to the destructor? 您的类构造函数是否初始化heightmap ,或者在到达析构函数时未初始化它?

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. 但是,您没有考虑到在执行程序期间可能多次调用析构函数。

In debug mode pointers are often set to NULL and memory blocks zeroed out. 在调试模式下,指针通常设置为NULL,并且内存块清零。 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 另请参见boost :: shared_ptr

It's quite possible that you're calling that dtor twice; 您很有可能两次调用了该dtor。 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; 尽管不是一个干净的解决方案,但想到的第一个解决方法是将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.]] 删除之后-没必要,但是当您在寻找为什么要两次销毁某些Terrain实例的解释时,肯定不会受到伤害!-)[[[很少的代码绝对没有您所展示的内容可以帮助我们解释发生双重破坏的原因。]]

It looks like the classic case of uninitialized pointer. 看起来像未初始化指针的经典情况。 As @Greg said, what if load() is not called from Terrain? 如@Greg所说,如果不从Terrain调用load()怎么办? I think you are not initializing the HeightMap* pointer inside the Terrain constructor. 我认为您没有在Terrain构造函数中初始化HeightMap*指针。 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. 在调试模式下,此指针可以设置为NULL,并且C ++保证删除NULL指针是有效操作,因此代码不会崩溃。 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. 但是,由于优化,在释放模式下,指针处于未初始化状态,并且您尝试释放一些随机的内存块,并且发生上述崩溃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM