This module is supplied as is; feel free to make whatever changes you so desire to it. It is relatively simple so that it can be placed into your situation easily. This document applies to AIX Version 3.2.
debug_malloc(size_t size) returns a buffer of size bytes by calling malloc, and storing the address into a linked list so that future calls to malloc can check to see if the boundary of the buffer is overwritten. debug_realloc(void *ptr, size_t size) returns a new structure of size bytes long in which the MIN(length of first allocation, size) bytes of memory are transferred to the new address. debug_free(void *ptr) frees the memory and removes that block from the linked list as well. While debugging, the check_pointers() routine may be called to see if a buffer has been overflowed. It returns 0 if there has been a buffer overrun.
Compile all other modules with:
cc -c -Dcalloc=debug_calloc -Dmalloc=debug_malloc \ -Drealloc=debug_realloc -Dfree=debug_free myfile.c /*provides: debug_malloc, debug_calloc, debug_free, check_pointers, */ /*external FUNCTIONS: malloc(), realloc(), free() */ #ifdef malloc #undef malloc #endif #include [stdio.h] #include [malloc.h] #define EXTRA_BUFFER (128) #define FILL_BUFFER (' ') #define MIN(a,b) ((a < b) ? a : b) #define MAX(a,b) ((a > b) ? a : b) void * bad_pointer; int went_over = 0; struct mem_pointers { char * pointer; /* points to a malloc'ed buffer */ size_t size_of_mem; /* size of buffer originally asked for */ struct mem_pointers *next_pointer; /* next item on list */ } *first_pointer = NULL; /* got to have someplace to start */ typedef struct mem_pointers mem_p; int check_pointers(); void add_pointer(void *ptr, size_t Size, mem_p **pointers); void *debug_malloc(size_t Size) { void *rc; static int opt_set = 0; if (! opt_set) mallopt(1,0); /* call the yorktown malloc() */ opt_set = 1; (void) check_pointers(); rc = malloc(Size + EXTRA_BUFFER + 4);/* Size + a buffer + 4 */ if (rc != NULL) add_pointer( rc, Size, &first_pointer);/* add to the list */ else return NULL; fprintf(stderr,"Fullfilled a request for %d bytes\n",Size); return (rc); /* return a pointer to the malloc'ed memory */ } mem_p * find_pointer(mem_p * fp, void * ptr) /* return the mem_p of the pointer */ { /* that has been previously malloc'd */ mem_p *p = fp; while (p && p->pointer != ptr) p = p-> next_pointer; return (p); } remove_pointer(mem_p * mp) /* return the mem_p of the pointer */ { /* that has been previously malloc'd */ mem_p *p; if (first_pointer == mp) { first_pointer = mp->next_pointer; } else { p = first_pointer; while (p && p->next_pointer != mp) p = p->next_pointer; if (p -> next_pointer == mp) p-> next_pointer = mp->next_pointer; } free(mp->pointer); free (mp); } void * debug_realloc( void * ptr, size_t new_size) { mem_p *mp; void * rc; check_pointers(); if (!(mp = find_pointer(first_pointer,ptr))) /* if we don't have the */ { fprintf(stderr,"ERROR: realloc called with a bad pointer %x \n", ptr); return NULL; } fprintf(stderr,"request to reallocate to %d up from %d\n", new_size, mp->size_of_mem); rc = malloc(new_size+EXTRA_BUFFER+4);/* malloc new size + a little xtra */ memcpy(rc, ptr, MIN(mp->size_of_mem,new_size));/* copy the contents */ memset(((char *) rc)+new_size, FILL_BUFFER, EXTRA_BUFFER); free(mp->pointer);/* free the other pointer */ mp->pointer = rc; /* set up pointer structures */ mp->size_of_mem = new_size; } void * debug_calloc(size_t a, size_t num) { int counter = 0; char *s, *r; s = r = debug_malloc(a * num); while (counter < a * num) *(r++) = '\0'; return (s); } void debug_free(void *addr) { mem_p *mp; mem_p *prev; if ((mp = find_pointer(first_pointer,addr)) == NULL) { free( addr ); return; } remove_pointer(mp); } /* check_pointers(): returns false (0) if there is a corrupted buffer, TRUE (1) otherwise */ int check_pointers() { char *s, *r; mem_p * p; int rc1 = 1, rc = 1 ; p = first_pointer; while (p) { rc = 1; s = (char *) p -> pointer; s += p->size_of_mem; r = s + EXTRA_BUFFER; while (s < r && rc) if (*(--r) != FILL_BUFFER) { rc = 0; rc1 = 0; bad_pointer = p->pointer; went_over = r - s +1; fprintf(stderr, "\nError: bad block %x, %d too many bytes written to it. size is %d\n", bad_pointer, went_over, p-> size_of_mem); } p = p->next_pointer; } return (rc1); } void add_pointer(void *ptr, size_t Size, mem_p **pointers) { char *s, *r; mem_p *p; s = (char *) ptr; s += Size; r = s + EXTRA_BUFFER; while (s < r) *(s++) = FILL_BUFFER; if (*pointers == NULL) { * pointers = malloc (sizeof (mem_p)); p = *pointers; } else { p = *pointers; while (p->next_pointer) p = p->next_pointer; p -> next_pointer = malloc (sizeof (mem_p)); p = p->next_pointer; } p->pointer = ptr; p->size_of_mem = Size; p->next_pointer = NULL; }