You can use valgrind with its memcheck tool on some systems.
http://valgrind.org/
There are other tools like this.
Or just write little wrappers for malloc and free that keep track of
everything. __FILE__ and __LINE__ can be useful for this-- your memory
tracker can keep track of where in the source the calls came from.
Something like this:
void *my_malloc(size_t size, const char *file, unsigned line)
{
void *ret = malloc(size);
static unsigned count = 0;
/* store ret in a list somewhere perhaps */
printf("%uth allocation of %p from %s:%u\n", count, ret, file, line);
count++;
return ret;
}
void my_free(void *p)
{
/* remove p from the list */
printf("Freeing %p\n", p);
free(p);
}
Then in something that's included by all source files:
extern void *my_malloc(size_t, const char *, unsigned);
extern void my_free(void *);
#define malloc(size) my_malloc(size, __FILE__, __LINE__)
#define free my_free
At the end of the program, anything left in the list is leaked.
Alternatively don't bother with a list, and just parse the output with a
scripting language-- you've got a record of all the allocations and
deallocations there. Do whichever's easier.
You can tell from what got printed out which allocations leaked. If you
run the program again (provided it doesn't depend on any external input
that might change), you can use a debugger to investigate the leaked
allocations as they are made.
Another way to do this is to use a debugger like gdb as a tracer; you
can set commands on a breakpoint to print a backtrace and then continue.
This might help you find the leaking backtraces. But you might not need
to resort to this.