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!