The GNU libc manual page for mcheck says that the MCHECK_FREE status means "The block was already freed." That would imply to me that the block was freed (at least) once. This answer seems to imply the same in the code example. However, the Linux manpage says quite explicitly that MCHECK_FREE means "A block of memory was freed twice." I modified the code example from the above answer to make it slightly more descriptive:
#include <stdio.h>
#include <stdlib.h>
#include <mcheck.h>
void print_status(enum mcheck_status status)
{
switch(status)
{
case MCHECK_DISABLED:
printf("MCHECK_DISABLED\n");
break;
case MCHECK_OK:
printf("MCHECK_OK\n");
break;
case MCHECK_HEAD:
printf("MCHECK_HEAD\n");
break;
case MCHECK_TAIL:
printf("MCHECK_TAIL\n");
break;
case MCHECK_FREE:
printf("MCHECK_FREE\n");
break;
}
}
void no_op(enum mcheck_status status) {}
int main()
{
mcheck(&no_op);
void* f = malloc(4);
print_status(mprobe(f));
free(f);
print_status(mprobe(f));
return 0;
}
When I run this code I get this output:
MCHECK_OK
MCHECK_HEAD
This means I'm clearly getting MCHECK_HEAD as a response when checking a freed block. Is this behaviour reliable? Is it reasonable to expect that the header of a block will always be clobbered when it is freed? Are there different implementations of mcheck/mprobe that will return MCHECK_FREE instead?