[alt.sources.amiga] Great memory alloc / dealloc tracker.

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!