rogers@iris.ucdavis.edu (Brewski Rogers) (08/18/90)
LOOK! Actual source code in alt.source! There are two files, tracker.c and tracker.h, They were run through more. :::::::::::::: tracker.c :::::::::::::: /***************************************************************************** * M E M O R Y T R A C K E R * This (supposedly) bulletproof memory alloc/dealloc tracker supports * all calls to AllocMem, FreeMem, malloc, calloc, realloc, and free. * It does so by replacing the actual call with a macro (see tracker.h) * The only functions you need to be aware of are MemTrackerReport, * and FreeUnFreedMem. Neither have any parameters. It is recommended * you call FreeUnFreedMem right before you exit to flush anything * you might have forgotten. * * Note: If anything fails horribly, the function Die(char *s) * (which you must supply yourself) gets called. * * Happy debugging! * Bruce Rogers - rogers@iris.ucdavis.edu * This program is public domain. * * Note that do to the implementation of free(), (see tracker.h) & it may not work exactly the way you expect. Works for me, though. !---------------------------[8/1/90 Bruce Rogers]---------------------------- * FreeUnFreedMem Call this before exiting. Frees anything you forgot to fre * MemTrackerReport Prints out info on what's still allocated. *****************************************************************************/ /* Currently supported functions: */ #undef AllocMem #undef FreeMem #undef free #undef malloc #undef calloc #undef realloc #include <exec/types.h> #include <exec/memory.h> #include <stdio.h> struct Track { struct Track *Next,*Prev; long Address; long Amount; long Range; char *Func; char *File; long Line; }; struct Track *memTrackerTop=NULL; /******************************************************************** * Prints out file,line,func info in pretty format. ********************************************************************/ char *LineInfo(file,line,func) char *file,*func; long line; { static char output[100]; char temp[60]; sprintf(temp,"[%s.%d]",file,line); sprintf(output,"%-20s %-16s ",temp,func); return(output); } /******************************************************************** * Keeps a linked list of info on what you allocated. ********************************************************************/ void *TrackAllocMem(amount,flags,file,line,func) long amount,flags,line; char *file,*func; { long address; struct Track *track; address=(long)AllocMem(amount,flags); if (! address) { if (amount > 0 && amount < 0xffffff) { printf("%s AllocMem(%d,%d) FAILED!\n", LineInfo(file,line,func),amount,flags); Die("Couldn't alloc mem!\n"); } else return(NULL); } track=AllocMem(sizeof(struct Track),0L); if (! track) { Die("TOO LITTLE MEM TOO ALLOC TRACKER INFO BLOCK! (you're doomed.)\n"); } track->Address=address; track->Range=track->Amount=amount; track->File=file; track->Line=line; track->Func=func; track->Prev=NULL; if (memTrackerTop) memTrackerTop->Prev=track; track->Next=memTrackerTop; memTrackerTop=track; return((void *)address); } struct Track *FindTrack(address,amount,file,line,func) long address,amount; { struct Track *track; track=memTrackerTop; while(track) { if ( (address>=track->Address) && (address<(track->Address+track->Range { if (address+amount > track->Address+track->Range) { printf("%s Illegal range free!\n",LineInfo(file,line,func)); FreeMem((void *)address,amount); return(NULL); } else return(track); } track=track->Next; } printf("%s Illegal memory pointer: %d\n",LineInfo(file,line,func),address); return(NULL); } /******************************************************************** * On calls to free or FreeMem, check to see if any mistakes are made. * If a FreeMem only frees a sub-block of its total memory, * (ie; p=AllocMem(1000,0L); FreeMem(p,500); FreeMem(p+500,500);) * the amount of data owned by that track node is updated, but some * errors can still slide by, since the track node only keeps * track of the original range of the data, and doesn't keep * track of the addresses and ranges of the new sub-blocks. * At least it won't complain if you do it right. * Note that because of the way the FreeMem() and free() macros * are implemented, Free-twice errors don't happen. * (unless you try REALLY hard.) ********************************************************************/ void TrackFreeMem(void *ptr,long amount,char *file,long line,char *func) { long address=(long)ptr; struct Track *track; track=memTrackerTop; track=FindTrack(address,amount,file,line,func); if (! track) return; if (amount == -1) amount=track->Amount; if (amount > track->Amount) { printf("%s Too much (%d bytes) freed!\n",LineInfo(file,line,func),amoun FreeMem((void *)address,amount); return; } if (track->Amount != amount) { /* * Unless you are doing tricky stuff, this is an error. * printf("%s: Short free. (%d bytes)\n", * LineInfo(file,line,func),amount); */ track->Amount-=amount; FreeMem((void *)address,amount); return; } if (track->Next) track->Next->Prev=track->Prev; if (track->Prev) track->Prev->Next=track->Next; else { memTrackerTop=track->Next; if (memTrackerTop) memTrackerTop->Prev=NULL; } FreeMem(track,sizeof(struct Track)); FreeMem((void *)address,amount); } void *TrackMalloc(amount,file,line,func) long amount,line; char *file,*func; { return(TrackAllocMem(amount,0,file,line,func)); } void TrackFree(void *ptr,char *file,long line,char *func) { TrackFreeMem(ptr,-1,file,line,func); } void *TrackRealloc(void *ptr,long newsize,char *file,long line,char *func) { void *new; struct Track *track; track=FindTrack(ptr,0,file,line,func); if (! track) { printf("%s Realloc failed!\n", LineInfo(track->File,track->Line,track->Func)); return; } new=TrackAllocMem(newsize,MEMF_CLEAR,file,line,func); memcpy(new,(void *)track->Address,track->Amount); TrackFreeMem(ptr,-1,file,line,func); return(new); } /*!****************************************************************** * Prints out info on what's still allocated. * Most recent first. ********************************************************************/ void MemTrackerReport() { struct Track *track,*temp; track=memTrackerTop; while(track != NULL) { if (track->Amount==track->Range) printf("%s hasn't freed %d bytes\n", LineInfo(track->File,track->Line,track->Func),track->Amount); else printf("%s hasn't freed %d of %d bytes\n", LineInfo(track->File,track->Line,track->Func), track->Amount,track->Range); temp=track; track=track->Next; } } /*!****************************************************************** * Call this before exiting. Frees anything you forgot to free. ********************************************************************/ void FreeUnFreedMem() { struct Track *track,*temp; long amount=0; track=memTrackerTop; while(track != NULL) { if (track->Amount==track->Range) FreeMem((void *)track->Address,track-> amount+=track->Amount; temp=track; track=track->Next; FreeMem(temp,sizeof(struct Track)); } memTrackerTop=NULL; if (amount) printf("%d bytes needed to be freed!\n",amount); } :::::::::::::: tracker.h :::::::::::::: /***************************************************************************** * T R A C K E R H E A D E R !---------------------------[8/1/90 Bruce Rogers]---------------------------- * Note that do to the implementation of free(), it may not work * exactly the way you expect. Works for me, though. *****************************************************************************/ #define AllocMem(x,y) TrackAllocMem(x,y,__FILE__,__LINE__,__FUNC__) #define FreeMem(x,y) TrackFreeMem(x,y,__FILE__,__LINE__,__FUNC__) #define malloc(x) TrackMalloc(x,__FILE__,__LINE__,__FUNC__) #define realloc(x,y) TrackRealloc(x,y,__FILE__,__LINE__,__FUNC__) #define calloc(x,y) TrackAllocMem(x*y,MEMF_CLEAR,__FILE__,__LINE__,__FUNC__ #define free(x) { if (x) TrackFree(x,__FILE__,__LINE__,__FUNC__); x=NUL void *TrackAllocMem(long,long,char *,long,char *), TrackFreeMem(void *,long,char *,long,char *), *TrackMalloc(long,char *,long,char *), TrackFree(void *,char *,long,char *), *TrackRealloc(void *,long,char *,long,char *); END_OF_FILE ------------------------------------------------------ Quantum _\/_ 2727 Eel Bruce (6502 RULES!) Rogers |\ Duck ( 0 0) Davis, Ca 95616 Quantum Duck Software, |\ \______/ / \\\ 916-756-2684 rogers@iris.ucdavis.edu |\ < < | \/ Cinnamon, Rock Candy, or Sugar? decisions decisions. \_________/ Quark!