home *** CD-ROM | disk | FTP | other *** search
Wrap
/* tracking memory allocator */ #ifdef TRACKER #include <exec/types.h> #include <exec/memory.h> #include <functions.h> #include <stdio.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 #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; { register 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)) == NULL) panic("tracker: can't alloc memory to record AllocMem data"); /* 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; { register 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->next) { /* 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'ed %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\tallocated in file %s at line %d, freed in file %s at line %d\n",where,amount,rp->file,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 FreeMem(where,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",MemAllocCount,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("freed a signal (%ld) that was never allocated, at file %s line %d\n", signal_num,file,line); TrackingSignalMask &= ~(1 << signal_num); } } void ReportUnfreedSignals() { if (TrackingSignalMask) fprintf("failed to free signals indicated by this mask: %8lx\n", TrackingSignalMask); printf("Total tracked AllocSignal calls %ld, FreeSignal calls %ld\n",SignalAllocCount,SignalFreeCount); } /* tracking lock and unlock */ struct TrackingLockData { struct FileLock *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; struct FileLock *TrackingLock(name, accessMode, file, line) char *name; long accessMode; char *file; int line; { register struct TrackingLockData *lp; struct FileLock *users_lock; users_lock = Lock(name, (long)accessMode); if (users_lock) { TrackerLockCount++; if ((lp = AllocMem((long)sizeof(struct TrackingLockData),0L)) == NULL) panic("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) panic("tracker: can't alloc memory to record lock filename"); strcpy(lp->name,name); } return(users_lock); } struct FileLock *TrackingDupLock(lock, file, line) struct FileLock *lock; char *file; int line; { register struct TrackingLockData *lp; struct FileLock *users_lock; users_lock = DupLock(lock); if (users_lock) { TrackerLockCount++; if ((lp = AllocMem((long)sizeof(struct TrackingLockData),0L)) == NULL) panic("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 TrackingUnLock(lock,file,line) struct FileLock *lock; char *file; int line; { register 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\tlocked at file %s line %d, freed at file %s line %d\n",lock,lp->name,lp->file,lp->line,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); } 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->line); } } 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",TrackerLockCount,TrackerUnLockCount); } TrackerExitReport() { ReportUnfreedMemory(); ReportUnfreedLocks(); ReportUnfreedSignals(); } #endif