Search code examples
cfreeglibc

free() : no double free detected


I have some problems with free() function:

#include <stdio.h>
#include <stdlib.h>
int main() {
    char *a=malloc(24);
    char *b=malloc(24);
    free(a);
    free(a);
}

there is a "* glibc detected * ./a.out: double free or corruption". That's not surprising because i used free() twice.

But now if i do that:

#include <stdio.h>
#include <stdlib.h>
int main() {
    char *a=malloc(24);
    char *b=malloc(24);
    free(a);
    free(b);
    free(a);
}

there are no errors from my computer, no double free error message, but as you can see there is double free in my code...

Do you know what's going wrong?


Solution

  • I can't answer why the double free doesn't happen to be detected in your second example other than to guess that libc's primary objective is to be performant by default. So checking for things like double-free probably isn't something the library puts much effort into detecting by default.

    However if you run the program with the MALLOC_CHECK_ environment variable set to 1 you do get a diagnostic on stderr (set the variable to 2 for an abort, 3 for an abort with the diagnostic and crashdump info written to stderr):

    $ gcc -o test test.c
    $ ./test
    $ MALLOC_CHECK_=1 ./test
    *** glibc detected *** ./test: free(): invalid pointer: 0x00000000015e4010 ***
    

    (Note the trailing underscore on the environment variable name).

    The behavior of libc's heap checking configured with MALLOC_CHECK_ is documented on the "Heap Consistency Checking" page:

    Another possibility to check for and guard against bugs in the use of malloc, realloc and free is to set the environment variable MALLOC_CHECK_. When MALLOC_CHECK_ is set, a special (less efficient) implementation is used which is designed to be tolerant against simple errors, such as double calls of free with the same argument, or overruns of a single byte (off-by-one bugs). Not all such errors can be protected against, however, and memory leaks can result. If MALLOC_CHECK_ is set to 0, any detected heap corruption is silently ignored; if set to 1, a diagnostic is printed on stderr; if set to 2, abort is called immediately. This can be useful because otherwise a crash may happen much later, and the true cause for the problem is then very hard to track down.