home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
200-299
/
ff280.lzh
/
Graph
/
divers
/
tracker.c
Wrap
C/C++ Source or Header
|
1989-11-20
|
12KB
|
425 lines
/* Resource tracking routines, by Karl Lehenbauer
Lattice version by David Gay.
This code is in the public domain
*/
/* tracking memory allocator */
#include <exec/types.h>
#include <exec/memory.h>
#include <stdio.h>
#include <string.h>
#include <proto/exec.h>
#include <proto/dos.h>
/* comment out the following line if you want locks freed twice reported
* at the cost of getting spurious resource error messages when
* reusing the lock */
/* #define FORGET_LOCKS_WHEN_UNLOCKED */
/* comment out the following line if you want memory freed twice reported
* at the cost of getting spurious resource error messages when
* freeing and reallocating memory */
#define FORGET_MEMORY_WHEN_FREED
/* make sure our invocations of the real routines on behalf of the user
don't cause us to recurse */
#ifdef AllocMem
#undef AllocMem
#undef FreeMem
#undef AllocSignal
#undef FreeSignal
#undef Lock
#undef UnLock
#undef DupLock
#undef ParentDir
#endif
/* my flags */
#define FREED_IT 1
struct TrackingAllocMemData
{
UBYTE *where; /* address returned by allocator */
long amount; /* number of bytes allocated */
long alloc_flags; /* flags passed to allocator */
char *file; /* filename of caller from the macro */
int line; /* line number of caller from macro */
long my_flags; /* flags internal to tracker */
struct TrackingAllocMemData *next; /* pointer to next entry */
};
struct TrackingAllocMemData *TrackingAllocMemList = NULL;
long MemAllocCount = 0, MemFreeCount = 0;
void *TrackingAllocMem(amount,flags,file,line)
long amount;
long flags;
char *file;
int line;
{
struct TrackingAllocMemData *rp;
UBYTE *users_memory;
/* perform the actual alloc */
users_memory = AllocMem(amount,flags);
/* if it succeeded, record tracking info */
if (users_memory)
{
MemAllocCount++;
if ((rp = AllocMem((long)sizeof(struct TrackingAllocMemData),0L)) == N
ULL)
fprintf(stderr, "tracker: can't alloc memory to record AllocMem da
ta");
/* add new alloc data entry to linked list */
rp->next = TrackingAllocMemList;
TrackingAllocMemList = rp;
/* shove in save values */
rp->amount = amount;
rp->alloc_flags = flags;
rp->where = users_memory;
rp->file = file;
rp->line = line;
rp->my_flags = 0;
}
/* return pointer to the space allocated */
return(users_memory);
}
void TrackingFreeMem(where,amount,file,line)
UBYTE *where;
long amount;
char *file;
int line;
{
struct TrackingAllocMemData *rp, *op, *freep;
MemFreeCount++;
/* scan the memory tracking list for a match */
for (rp = TrackingAllocMemList, op = NULL; rp != NULL; op = rp, rp = rp->ne
xt)
{
/* if we matched the address */
if (rp->where == where)
{
/* if they got the amount wrong, tell them */
if (rp->amount != amount)
{
fprintf(stderr,"freed addr %lx OK but length differs, talloc'e
d %ld, freed %ld,\n\tallocated at file %s line %d, freed at file %s line %d\n",
where,rp->amount,amount,rp->file,rp->line,file,line);
}
#ifndef FORGET_MEMORY_WHEN_FREED
/* if it's already free, tell them they freed twice */
if (rp->my_flags & FREED_IT)
{
fprintf(stderr,"freed memory twice at %lx, amount %ld,\n\tallo
cated in file %s at line %d, freed in file %s at line %d\n",where,amount,rp->fil
e,rp->line,file,line);
return;
}
else
{
/* mark this entry as free */
rp->my_flags |= FREED_IT;
}
#else
/* remove entry from linked list and free it */
if (op != NULL) op->next = rp->next;
else
TrackingAllocMemList = rp->next;
freep = rp;
rp = rp->next;
FreeMem(freep,(long)sizeof(struct TrackingAllocMemData));
#endif
/* Munge memory block */
memset((char *)where, amount, 3); /* Set to an odd number ... */
FreeMem(where,(long)amount);
return;
}
}
fprintf(stderr,"Freed memory at %lx of amount %ld that wasn't allocated,\n\
tfreed at file %s line %d\n",where,amount,file,line);
FreeMem(where,amount);
}
void ReportUnfreedMemory()
{
struct TrackingAllocMemData *rp = TrackingAllocMemList, *freep;
while (rp != NULL)
{
if (!(rp->my_flags & FREED_IT))
{
fprintf(stderr,"FreeMem was never called for memory at %lx, amount
%ld,\n\tthe alloc was performed at file %s line %d\n",rp->where,rp->amount,rp->
file,rp->line);
}
freep = rp;
rp = rp->next;
FreeMem(freep,(long)sizeof(struct TrackingAllocMemData));
}
printf("Total tracked AllocMem calls %ld, FreeMem calls %ld\n",MemAllocCoun
t,MemFreeCount);
}
/* track signals */
/* tracking AllocSignal doesn't currently track where it was called from */
long TrackingSignalMask = 0;
long SignalAllocCount = 0, SignalFreeCount = 0;
long TrackingAllocSignal(signal_num,file,line)
long signal_num;
char *file;
int line;
{
SignalAllocCount++;
signal_num = AllocSignal(signal_num);
if (signal_num != -1)
TrackingSignalMask |= (1 << signal_num);
return(signal_num);
}
void TrackingFreeSignal(signal_num,file,line)
long signal_num;
char *file;
int line;
{
SignalFreeCount++;
if (!(TrackingSignalMask & (1 << signal_num)))
{
fprintf(stderr, "freed a signal (%ld) that was never allocated, at fil
e %s line %d\n",
signal_num,file,line);
}
TrackingSignalMask &= ~(1 << signal_num);
}
void ReportUnfreedSignals()
{
if (TrackingSignalMask)
fprintf(stderr, "failed to free signals indicated by this mask: %8lx\n
",
TrackingSignalMask);
printf("Total tracked AllocSignal calls %ld, FreeSignal calls %ld\n",Signal
AllocCount,SignalFreeCount);
}
/* tracking lock and unlock */
struct TrackingLockData
{
BPTR lock; /* lock returned by Lock */
char *name; /* name of file that was locked */
long accessMode; /* access mode of the file that was locked */
char *file; /* ptr to file name of line of caller */
int line; /* ptr to line number text of locker */
long my_flags; /* flags internal to tracker */
struct TrackingLockData *next; /* pointer to next entry */
};
/* flags */
#define CREATED_BY_DUPLOCK 1
struct TrackingLockData *TrackingLockList = NULL;
long TrackerLockCount = 0, TrackerUnLockCount = 0;
BPTR TheTrackingLock(name, accessMode, file, line)
char *name;
long accessMode;
char *file;
int line;
{
struct TrackingLockData *lp;
BPTR users_lock;
users_lock = Lock(name, (long)accessMode);
if (users_lock)
{
TrackerLockCount++;
if ((lp = AllocMem((long)sizeof(struct TrackingLockData),0L)) == NULL)
fprintf(stderr, "tracker: can't alloc memory to record lock data")
;
/* add new alloc data entry to linked list */
lp->next = TrackingLockList;
TrackingLockList = lp;
/* shove in save values */
lp->accessMode = accessMode;
lp->file = file;
lp->line = line;
lp->my_flags = 0;
lp->lock = users_lock;
/* alloc space for filename and save */
if ((lp->name = AllocMem((long)(strlen(name)+1),0L)) == NULL)
fprintf(stderr, "tracker: can't alloc memory to record lock filena
me");
strcpy(lp->name,name);
}
return(users_lock);
}
BPTR TheTrackingDupLock(lock, file, line)
BPTR lock;
char *file;
int line;
{
struct TrackingLockData *lp;
BPTR users_lock;
users_lock = DupLock(lock);
if (users_lock)
{
TrackerLockCount++;
if ((lp = AllocMem((long)sizeof(struct TrackingLockData),0L)) == NULL)
fprintf(stderr, "tracker: can't alloc memory to record lock data")
;
/* add new alloc data entry to linked list */
lp->next = TrackingLockList;
TrackingLockList = lp;
lp->file = file;
lp->line = line;
lp->name = NULL;
lp->lock = users_lock;
lp->my_flags = CREATED_BY_DUPLOCK;
}
return(users_lock);
}
void TheTrackingUnLock(lock,file,line)
BPTR lock;
char *file;
int line;
{
struct TrackingLockData *lp, *op, *freep;
TrackerUnLockCount++;
/* scan the lock tracking list for a match */
for (lp = TrackingLockList, op = NULL; lp != NULL; op = lp, lp = lp->next)
{
/* if we matched the lock */
if (lp->lock == lock)
{
#ifndef FORGET_LOCKS_WHEN_UNLOCKED
/* if it's already free, tell them they freed twice */
if (lp->my_flags & FREED_IT)
{
fprintf(stderr,"freed lock twice, lock %lx, filename %s\n\tloc
ked at file %s line %d, freed at file %s line %d\n",lock,lp->name,lp->file,lp->l
ine,file,line);
return;
}
else
{
/* mark this entry as free */
lp->my_flags |= FREED_IT;
}
#else
if (op != NULL) op->next = lp->next;
else TrackingLockList = lp->next;
freep = lp;
lp = lp->next;
if (lp->name != NULL)
FreeMem(lp->name,(long)(strlen(lp->name)+1));
FreeMem(freep,(long)(sizeof(struct TrackingLockData)));
#endif
UnLock(lock);
return;
}
}
fprintf(stderr,"Freed lock %lx that hadn't been allocated at file %s line %
d\n",lock,file,line);
}
BPTR TheTrackingParentDir(BPTR lock, char *file, int line)
{
struct TrackingLockData *lp;
BPTR users_lock;
users_lock = ParentDir(lock);
if (users_lock)
{
TrackerLockCount++;
if ((lp = AllocMem((long)sizeof(struct TrackingLockData),0L)) == NULL)
fprintf(stderr, "tracker: can't alloc memory to record lock data")
;
/* add new alloc data entry to linked list */
lp->next = TrackingLockList;
TrackingLockList = lp;
/* shove in save values */
lp->accessMode = 0;
lp->file = file;
lp->line = line;
lp->my_flags = 0;
lp->lock = users_lock;
lp->name = NULL;
}
return(users_lock);
}
void ReportUnfreedLocks()
{
struct TrackingLockData *lp = TrackingLockList, *freep;
while (lp != NULL)
{
if (!(lp->my_flags & FREED_IT))
{
if (lp->my_flags & CREATED_BY_DUPLOCK)
{
fprintf(stderr,"UnLock was never called for lock %lx,\n\It was
created by DupLock at file %s line %d\n",lp->lock,lp->file,lp->line);
}
else
{
fprintf(stderr,"UnLock was never called for lock %lx,\n\It was
created by a Lock of %s\nat file %s line %d\n",lp->lock,lp->name,lp->file,lp->l
ine);
}
}
if (lp->name != NULL)
FreeMem(lp->name,(long)(strlen(lp->name)+1));
freep = lp;
lp = lp->next;
FreeMem(freep,(long)sizeof(struct TrackingLockData));
}
printf("Total tracked Lock and DupLock calls %ld, UnLock calls %ld\n",Track
erLockCount,TrackerUnLockCount);
}
void TrackerExitReport()
{
ReportUnfreedMemory();
ReportUnfreedLocks();
ReportUnfreedSignals();
}