September, 1995 - Vol. 2 No. 9
//************************************************* // DMALLOC.C - Contains "thunk" functions for // trapping calls to malloc and free. Also, // contains dreport(), which writes a memory // status report to the file DREPORT.LST. // #include <stdlib.h> #include <stdio.h> #include <malloc.h> #include <string.h> #define GROWBY 100 //----Compile only if DEBUG is defined #ifdef __DEBUG //----Here's the structure we save for each // memory allocation typedef struct _DLIST { void *ptr; char *file; int line; } DLIST; //----Global variables DLIST **dlist; int dlist_cnt; int dlist_size; //************************************************* // dmalloc - This is our thunk for malloc // void *dmalloc( char *file, int line, size_t size ) { void *ptr; DLIST **new_dlist; int new_dlist_size; //----Create list the first time through if ( !dlist ) { dlist = (DLIST **) malloc( sizeof(DLIST *) * GROWBY ); if ( !dlist ) return NULL; dlist_cnt = 0; dlist_size = GROWBY; } //----Enlarge list when necessary if ( dlist_cnt+1 > dlist_size ) { new_dlist_size = min( dlist_size+GROWBY, 16380 ); new_dlist = (DLIST **) realloc( dlist, sizeof(DLIST *) * new_dlist_size ); if ( !new_dlist ) return NULL; // Not enough memory dlist = new_dlist; dlist_size = new_dlist_size; } //----Allocate memory for new DLIST object dlist[dlist_cnt] = (DLIST *)malloc( sizeof(DLIST) ); if ( !dlist[dlist_cnt] ) return NULL; // Not enough memory dlist[dlist_cnt]->file = malloc( strlen(file)+1 ); if ( !dlist[dlist_cnt]->file ) { free ( dlist[dlist_cnt] ); return NULL; // Not enough memory } //----Allocate the requested memory ptr = malloc( size ); if ( !ptr ) return NULL; // Not enough memory //----Update dlist with pointer information dlist[dlist_cnt]->ptr = ptr; dlist[dlist_cnt]->line = line; strcpy( dlist[dlist_cnt]->file, file ); ++dlist_cnt; //----Return pointer to caller return ptr; } //************************************************* // dfree - This is our thunk for free // void dfree( void *ptr ) { int i = 0; //----Free the memory as requested free( ptr ); //----Search for pointer in dlist while( i < dlist_cnt && ptr != dlist[i]->ptr ) ++i; if ( i == dlist_cnt ) // Not in dlist return; //----Free associated dlist entry free( dlist[i]->file ); free( dlist[i] ); --dlist_cnt; //----Move last entry to fill the hole in dlist if ( dlist_cnt > 0 && dlist_cnt != i ) dlist[i] = dlist[dlist_cnt]; } //************************************************* // dreport - Writes the current dlist to a file int dreport( void ) { int i; FILE *fp; char workstr[80]; fp = fopen( "DREPORT.LST", "w" ); if ( !fp ) return 0; sprintf( workstr, "\n%d entries in dlist\n\n", dlist_cnt ); fputs( workstr, fp ); for ( i=0; i<dlist_cnt; i++ ) { sprintf( workstr, "Line: %5.5d File: %s\n", dlist[i]->line, dlist[i]->file ); fputs( workstr, fp ); } fclose( fp ); return 1; } #endif
Return to "Debugging Tip - Using thunk functions to track down memory leaks"
Copyright (c) 1996 The Cobb Group, a division of Ziff-Davis Publishing Company. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of Ziff-Davis Publishing Company is prohibited. The Cobb Group and The Cobb Group logo are trademarks of Ziff-Davis Publishing Company.