+7  A: 

You can use gdb, but I would first try Valgrind. See the quick start guide.

Matthew Flaschen
+3  A: 

There are at least two possible situations:

  1. you are deleting the same entity twice
  2. you are deleting something that wasn't allocated

For the first one I strongly suggest NULL-ing all deleted pointers.

You have three options:

  1. overload new and delete and track the allocations
  2. yes, use gdb -- then you'll get a backtrace from your crash, and that'll probably be very helpful
  3. as suggested -- use Valgrind -- it isn't easy to get into, but it will save you time thousandfold in the future...
Kornel Kisielewicz
how is it done in gdb?
Phenom
2. would cause corruption, but I don't think this message would generally appear, since the sanity checking is only done on the heap. However, I think 3. heap buffer overflow is possible.
Matthew Flaschen
A: 

Three basic rules:

  1. Set pointer to NULL after free
  2. Check for NULL before freeing.
  3. Initialise pointer NULL in the start.

Combination of these three works quite well.

Jack
I'm not C expert, but I usually can keep my head above water. Why #1? Is it just so your program flat out crashes when you try and access a free'd pointer, and not just a silent error?
Precision
@Precision: Yes, that's the point. It is a good practice: having a pointer to deleted memory is a risk.
ereOn
@ereOn: Thanks. I've just had a couple classes on C, and never had to write code that with anyone else, so never really had this problem. Seems like a very good practice though.
Precision
Strictly speaking I think #2 is unnecessary as most compilers will allow you to try to delete a null pointer without this causing a problem. I'm sure someone will correct me if I'm wrong. :)
Robin Welch
A: 

If you're using glibc, you can set the MALLOC_CHECK_ environment variable to 2, this will cause glibc to use an error tolerant version of malloc, which will cause your program to abort at the point where the double free is done.

You can set this from gdb by using the set environment MALLOC_CHECK_ 2 command before running your program; the program should abort, with the free() call visible in the backtrace.

see the man page for malloc() for more information

Hasturkun
A: 

Are you using smart pointers such as Boost shared_ptr? If so, check if you are directly using the raw pointer anywhere by calling get(). I've found this to be quite a common problem.

For example, imagine a scenario where a raw pointer is passed (maybe as a callback handler, say) to your code. You might decide to assign this to a smart pointer in order to cope with reference counting etc. Big mistake: your code doesn't own this pointer unless you take a deep copy. When your code is done with the smart pointer it will destroy it and attempt to destroy the memory it points to since it thinks that no-one else needs it, but the calling code will then try to delete it and you'll get a double free problem.

Of course, that might not be your problem here. At it's simplest here's an example which shows how it can happen. The first delete is fine but the compiler senses that it's already deleted that memory and causes a problem. That's why assigning 0 to a pointer immediately after deletion is a good idea.

int main(int argc, char* argv[])
{
    char* ptr = new char[20];

    delete ptr;
    ptr = 0;  // Comment me out and watch me crash and burn.
    delete ptr;
}
Robin Welch
I didn't use any delete commands in my program. Could this still be the problem?
Phenom
@Phenom: Why did you not use deletes? Is it because you're using smart pointers? Presumably you are using new in your code to create objects on the heap? If the answer to both of these is yes then are you using get / set on the smart pointers to copy around raw pointers? If so, don't! You'd be breaking the reference counting. Alternatively you could be assigning a pointer from library code you're calling to a smart pointer. If you don't 'own' the memory pointed to then don't do it, as the both the library and the smart pointer will try to delete it.
Robin Welch