+1  A: 

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.

Greg Hewgill
Yep, that was it. I thought for sure heightmap* was being set (not in the constructor, but in a setter method), alas it was not. Thanks, Greg!
Mossen
Always initialize all your pointers during construction. A null pointer can be safely deleted (no-op). If your constructor setted the pointer to 0 in the initialization list then the code would be correct from the beginning.
David Rodríguez - dribeas
And of course there might be copy construction and/or assignment that make two objects pointing to the same memory zone...
Matthieu M.
A: 

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

Alex Martelli
+1  A: 

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

Anders K.
Thanks, I did not realize that about debug mode...I'm used to coding in Java...I will look into the auto_ptr!
Mossen
+1, also take a look at `scoped_ptr<>` and `unique_ptr<>`, either from boost or std::tr1. They are different solutions to smart pointer memory management.
David Rodríguez - dribeas
A: 

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.

Naveen