Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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

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.]]

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top