Originally Posted by
awsdert
I'm not a fan of the 0xDEADBEEF idea that was suggested as that requires extra variables to keep track of it's position...
If anybody is here looking for the "xDEADBEEF" idea, here it is:
Here's some bad code:
Code:
int main(void)
{
char *a;
a = my_malloc(17);
memset(a,0,17);
my_free(a);
a = my_malloc(17);
memset(a,0,18);
my_free(a);
return 0;
}
Note that nobody hast to keep track of extra variables. You just have to use my_malloc() and my_free() rather than malloc() and free().
Here's what happens when you run it:
Code:
my_malloc()
my_free()
my_malloc()
my_free()
Corruption detected - block trailer is trashed - get out the debugger!
That "Corruption detected" message is generated when my_free() is called.
And here is the tiny implementation I hacked up, less than a printed page of code
Code:
#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#include <stdlib.h>
#define HEADER_MAGIC 0xF00DBEEFU
unsigned char trailer_magic[4] = {0xDE, 0xAD, 0xBE, 0xEF};
struct malloc_header {
size_t magic;
size_t size;
};
static void *my_malloc(size_t size) {
void *raw;
struct malloc_header *hdr;
unsigned char *data;
printf("my_malloc()\n");
raw = malloc(size+sizeof(struct malloc_header)+sizeof(trailer_magic));
if(raw == NULL) return NULL;
hdr = raw;
data = raw;
data += sizeof(struct malloc_header);
hdr->magic = HEADER_MAGIC;
hdr->size = size;
memcpy(data+size,trailer_magic,sizeof(trailer_magic));
return data;
}
void my_free(void *ptr) {
printf("my_free()\n");
struct malloc_header *hdr = ptr;
unsigned char *data = ptr;
hdr--;
if(hdr->magic != HEADER_MAGIC) {
fprintf(stderr, "That's weird - not allocated with my_magic or trashed\n");
exit(0);
}
if(memcmp(trailer_magic, data+hdr->size, sizeof(trailer_magic)) != 0) {
fprintf(stderr, "Corruption detected - block trailer is trashed - get out the debugger!\n");
exit(0);
}
// Clear out the magic values, allowing us to detect double frees
memset(data+hdr->size, 0, sizeof(trailer_magic));
hdr->magic = 0;
free(hdr);
}
Implementing my_realloc() and my_calloc() is left to the user.
You could also add a "my_checkptr()" so you could validate that your heap hasn't been trashed.
e.g.
Code:
strcat(ptr, "foo and bar");
my_checkptr(ptr); // Doublecheck that the buffer hasn't been exceeded
And of course with the correct #defines all of this could be replaced by plain old malloc() and free() in your "release" build.