11/14/94 DEBUG_MALLOC.C /* debug_malloc.c SPECIAL NOTICES Information in this document is correct to the best of our knowledge at the time of this writing. Please send feedback by fax to "AIXServ Information" at (512) 823-5972. Please use this information with care. IBM will not be responsible for damages of any kind resulting from its use. The use of this information is the sole responsibility of the customer and depends on the customer's ability to eval- uate and integrate this information into the customer's operational environment. +----------------------------------------------------------+ | | | | NOTE: The information in this document has NOT been | | | verified for AIX 4.1. | | | +----------------------------------------------------------+ */ /* *********** NOTE: NOT SUPPORTED BY IBM ********************* *** 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 without too *** much hassle on your part. This document applies to AIX 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 overrrun. 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 #include #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; } 11/14/94 READER'S COMMENTS Please fax this form to (512) 823-5972, attention "AIXServ Informa- tion". Use this form to tell us what you think about this document. If you have found errors in it, or if you want to express your opinion about it (such as organization, subject matter, appearance) or make sug- gestions for improvement, this is the form to use. If you need technical assistance, contact your local branch office, point of sale, or 1-800-CALL-AIX (for information about support offer- ings). These services may be billable. For defect assistance, call 1-800-237-5511. Faxes on a variety of subjects may be ordered free of charge from 1-800-IBM-4FAX. When you send comments to IBM, you grant IBM a nonexclusive right to use or distribute your comments in any way it believes appropriate without incurring any obligation to you. Be sure to print your name and fax number below if you would like a reply: Name: Fax Phone Number: ______________________________________________________________________ ______________________________________________________________________ ______________________________________________________________________ ______________________________________________________________________ ______________________________________________________________________ ______________________________________________________________________ ______________________________________________________________________ ______________________________________________________________________ ______________________________________________________________________ ______________________________________________________________________ ______________________________________________________________________ ______________________________________________________________________ ______________________________________________________________________ ______________________________________________________________________ ______________________________________________________________________ END OF DOCUMENT (debug.malloc.c.lng)