views:

6053

answers:

4

In linux environment, when getting "glibc detected *** free(): invalid pointer" errors, how do I identify which line of code is causing it?

Is there a way to force an abort? I recall there being an ENV var to control this?

How to set a breakpoint in gdb for the glibc error?

+1  A: 

In general, it looks like you might have to recompile glibc, ugh.

You don't say what environment you're running on, but if you can recompile your code for OS X, then its version of libc has a free() that listens to this environment variable:

MallocErrorAbort             If set, causes abort(3) to be called if an
                              error was encountered in malloc(3) or
                              free(3) , such as a calling free(3) on a
                              pointer previously freed.

The man page for free() on OS X has more information.

If you're on Linux, then try Valgrind, it can find some impossible-to-hunt bugs.

Adrian
+2  A: 

How to set a breakpoint in gdb?

(gdb) b filename:linenumber // e.g. b main.cpp:100

Is there a way to force an abort? I recall there being an ENV var to control this?

I was under the impression that it aborted by default. Make sure you have the debug version installed.

Or use libdmalloc5: "Drop in replacement for the system's malloc', realloc', calloc', free' and other memory management routines while providing powerful debugging facilities configurable at runtime. These facilities include such things as memory-leak tracking, fence-post write detection, file/line number reporting, and general logging of statistics."

Add this to your link command

-L/usr/lib/debug/lib -ldmallocth

gdb should automatically return control when glibc triggers an abort.

Or you can set up a signal handler for SIGABRT to dump the stacktrace to a fd (file descriptor). Below, mp_logfile is a FILE*

void *array[512 / sizeof(void *)]; // 100 is just an arbitrary number of backtraces, increase if you want.
size_t size;

size = backtrace (array, 512 / sizeof(void *));
backtrace_symbols_fd (array, size, fileno(mp_logfile));
mat_geek
+2  A: 

I recommend you get valgrind:

valgrind --tool=memcheck --leak-check=full ./a.out

dicroce
You will have multiple runs so get valgrind to output to a file name based on the current time.valgrind--tool=memcheck --leak-check=full --log-file=`date +%s`-vg.txt ./a.out
mat_geek
+4  A: 

I believe if you setenv MALLOC_CHECK_ to 2, glibc will call abort() when it detects the "free(): invalid pointer" error. Note the trailing underscore in the name of the environment variable.

If MALLOC_CHECK_ is 1 glibc will print "free(): invalid pointer" (and similar printfs for other errors). If MALLOC_CHECK_ is 0, glibc will silently ignore such errors and simply return. If MALLOC_CHECK_ is 3 glibc will print the message and then call abort(). I.e. its a bitmask.

You can also call mallopt(M_CHECK_ACTION, arg) with an argument of 0-3, and get the same result as with MALLOC_CHECK_.

Since you're seeing the "free(): invalid pointer" message I think you must already be setting MALLOC_CHECK_ or calling mallopt(). By default glibc does not print those messages.

As for how to debug it, installing a handler for SIGABRT is probably the best way to proceed. You can set a breakpoint in your handler or deliberately trigger a core dump.

DGentry
where can I set MALLOC_CHECK so that it takes effect?
Nathan Fellman