13
typedef struct memoryBlock {
14
void* memoryLocation; /* Malloc address */
15
size_t blockSize; /* Block size */
16
char* programLocation; /* Program address: file, line */
17
struct memoryBlock* nextBlock; /* Next memory block */
21
static MemoryBlock *theRoot = NULL;
22
static char tmpStr[255];
25
static PthreadMutex leaksMutex;
28
unsigned int PrintMemoryBlocks(); /* Forward declaration */
30
/* *************************************** */
32
void* myMalloc(size_t theSize, int theLine, char* theFile) {
33
MemoryBlock *tmpBlock;
35
#if defined(MULTITHREADED)
36
accessMutex(&leaksMutex, "myMalloc");
39
tmpBlock = (MemoryBlock*)malloc(sizeof(MemoryBlock));
41
if(tmpBlock == NULL) {
42
traceEvent(TRACE_WARNING, "Malloc error (not enough memory): %s, %d\n",
45
#if defined(MULTITHREADED)
46
releaseMutex(&leaksMutex);
51
tmpBlock->blockSize = theSize;
52
tmpBlock->memoryLocation = malloc(theSize);
53
memset(tmpBlock->memoryLocation, 0xee, theSize); /* Fill it with garbage */
54
tmpBlock->alreadyTraced = 0;
56
allocatedMemory += theSize;
58
if(tmpBlock->memoryLocation == NULL) {
59
traceEvent(TRACE_WARNING, "Malloc error (not enough memory): %s, %d (size = %d)\n",
60
theFile, theLine, (int)theSize);
61
#if defined(MULTITHREADED)
62
releaseMutex(&leaksMutex);
67
if(snprintf(tmpStr, sizeof(tmpStr), "file %s, line %d.", theFile, theLine) < 0)
68
traceEvent(TRACE_ERROR, "Buffer overflow!");
69
tmpBlock->programLocation = strdup(tmpStr);
70
tmpBlock->nextBlock = theRoot;
73
#if defined(MULTITHREADED)
74
releaseMutex(&leaksMutex);
77
return(tmpBlock->memoryLocation);
80
/* *************************************** */
82
void* myCalloc(size_t numObj, size_t theSize, int theLine, char* theFile) {
83
int numElems = numObj*theSize;
84
void* thePtr = myMalloc(numElems, theLine, theFile);
87
memset(thePtr, '\0', numElems);
92
/* *************************************** */
94
void* myRealloc(void* thePtr, size_t theSize, int theLine, char* theFile) {
95
MemoryBlock *theScan, *lastPtr, *theNewPtr;
97
#if defined(MULTITHREADED)
98
accessMutex(&leaksMutex, "myRealloc");
103
while((theScan != NULL) && (theScan->memoryLocation != thePtr)) {
105
theScan = theScan->nextBlock;
108
if(theScan == NULL) {
109
traceEvent(TRACE_WARNING, "Realloc error (Ptr %p NOT allocated): %s, %d\n",
110
thePtr, theFile, theLine);
111
#if defined(MULTITHREADED)
112
releaseMutex(&leaksMutex);
116
theNewPtr = myMalloc(theSize, theLine, theFile);
118
if(theSize > theScan->blockSize)
119
memcpy(theNewPtr, thePtr, theScan->blockSize);
121
memcpy(theNewPtr, thePtr, theSize);
123
free(theScan->memoryLocation);
124
free(theScan->programLocation);
126
if(theScan == theRoot)
127
theRoot = theRoot->nextBlock;
129
lastPtr->nextBlock = theScan->nextBlock;
133
#if defined(MULTITHREADED)
134
releaseMutex(&leaksMutex);
141
/* *************************************** */
143
void myFree(void **thePtr, int theLine, char* theFile) {
144
MemoryBlock *theScan, *lastPtr;
146
#if defined(MULTITHREADED)
147
accessMutex(&leaksMutex, "myFree");
152
while((theScan != NULL) && (theScan->memoryLocation != *thePtr)) {
154
theScan = theScan->nextBlock;
157
if(theScan == NULL) {
158
traceEvent(TRACE_WARNING, "Free error (Ptr %p NOT allocated): %s, %d\n",
159
*thePtr, theFile, theLine);
160
#if defined(MULTITHREADED)
161
releaseMutex(&leaksMutex);
165
allocatedMemory -= theScan->blockSize;
167
free(theScan->memoryLocation);
168
free(theScan->programLocation);
170
if(theScan == theRoot)
171
theRoot = theRoot->nextBlock;
173
lastPtr->nextBlock = theScan->nextBlock;
179
#if defined(MULTITHREADED)
180
releaseMutex(&leaksMutex);
184
/* *************************************** */
186
char* myStrdup(char* theStr, int theLine, char* theFile) {
188
int len = strlen(theStr);
190
theOut = (char*)myMalloc((len+1), theLine, theFile);
191
strncpy(theOut, theStr, len);
197
/* *************************************** */
199
void resetLeaks(void) {
200
MemoryBlock *theScan;
204
while(theScan != NULL) {
205
theScan->alreadyTraced = 1;
206
theScan = theScan->nextBlock;
209
allocatedMemory = 0; /* Reset counter */
212
/* *************************************** */
214
unsigned int PrintMemoryBlocks(void) {
215
MemoryBlock *theScan;
217
unsigned int totMem = 0;
221
while(theScan != NULL) {
224
if(!theScan->alreadyTraced) {
225
traceEvent(TRACE_INFO,"Block %5d (addr %p, size %4d): %s\n", i++,
226
theScan->memoryLocation, theScan->blockSize, theScan->programLocation);
227
totMem += theScan->blockSize;
230
theScan->alreadyTraced = 1;
231
tmp = theScan->memoryLocation;
232
theScan = theScan->nextBlock;
235
traceEvent(TRACE_INFO,"\nTotal allocated memory: %u bytes\n\n", totMem);
237
/* PrintMemoryBlocks(); */
242
/* *************************************** */
244
size_t GimmePointerSize(void* thePtr) {
245
MemoryBlock *theScan;
249
while((theScan != NULL) && (theScan->memoryLocation != thePtr))
250
theScan = theScan->nextBlock;
252
if(theScan == NULL) {
253
traceEvent(TRACE_WARNING, "GimmePointerSize error: Ptr %p NOT allocated\n", thePtr);
256
return(theScan->blockSize);
259
/* *************************************** */
261
int GimmePointerInfo(void* thePtr) {
262
MemoryBlock *theScan;
266
while((theScan != NULL) && (theScan->memoryLocation != thePtr))
267
theScan = theScan->nextBlock;
269
if(theScan == NULL) {
270
traceEvent(TRACE_WARNING, "GimmePointerInfo error: Ptr %p NOT allocated\n", thePtr);
273
traceEvent(TRACE_WARNING, "Block (addr %p, size %d): %s\n", theScan->memoryLocation,
274
theScan->blockSize, theScan->programLocation);
279
/* *************************************** */
281
void myAddLeak(void* thePtr, int theLine, char* theFile) {
282
MemoryBlock *tmpBlock;
287
tmpBlock = (MemoryBlock*)malloc(sizeof(MemoryBlock));
289
if(tmpBlock == NULL) {
290
traceEvent(TRACE_WARNING, "Malloc error (not enough memory): %s, %d\n",
295
tmpBlock->blockSize = 0;
296
tmpBlock->memoryLocation = thePtr;
297
if(snprintf(tmpStr, sizeof(tmpStr), "file %s, line %d.", theFile, theLine) < 0)
298
traceEvent(TRACE_ERROR, "Buffer overflow!");
299
tmpBlock->programLocation = strdup(tmpStr);
300
tmpBlock->nextBlock = theRoot;
304
/* *************************************** */
306
void myRemoveLeak(void* thePtr, int theLine, char* theFile) {
307
MemoryBlock *theScan, *lastPtr;
311
while((theScan != NULL) && (theScan->memoryLocation != thePtr)) {
313
theScan = theScan->nextBlock;
316
if(theScan == NULL) {
317
traceEvent(TRACE_WARNING, "Free block error (Ptr %p NOT allocated): %s, %d\n",
318
thePtr, theFile, theLine);
321
free(theScan->programLocation);
323
if(theScan == theRoot)
324
theRoot = theRoot->nextBlock;
326
lastPtr->nextBlock = theScan->nextBlock;
332
/* *************************************** */
334
void initLeaks(void) {
336
createMutex(&leaksMutex);
340
/* *************************************** */
342
void termLeaks(void) {
345
deleteMutex(&leaksMutex);
349
/* ************************************ */
351
void* ntop_malloc(unsigned int sz, char* file, int line) {
354
traceEvent(TRACE_WARNING, "malloc(%d) [%s] @ %s:%d",
355
sz, formatBytes(allocatedMemory, 0), file, line);
358
return(myMalloc(sz, line, file));
361
/* ************************************ */
363
void* ntop_calloc(unsigned int c, unsigned int sz, char* file, int line) {
365
traceEvent(TRACE_WARNING, "calloc(%d,%d) [%s] @ %s:%d",
366
c, sz, formatBytes(allocatedMemory, 0), file, line);
368
return(myCalloc(c, sz, line, file));
371
/* ************************************ */
373
void* ntop_realloc(void* ptr, unsigned int sz, char* file, int line) {
375
traceEvent(TRACE_WARNING, "realloc(%p,%d) [%s] @ %s:%d",
376
ptr, sz, formatBytes(allocatedMemory, 0), file, line);
378
return(myRealloc(ptr, sz, line, file));
381
/* ************************************ */
383
char* ntop_strdup(char *str, char* file, int line) {
385
traceEvent(TRACE_WARNING, "strdup(%s) [%s] @ %s:%d", str,
386
formatBytes(allocatedMemory, 0), file, line);
388
return(myStrdup(str, line, file));
391
/* ************************************ */
393
void ntop_free(void **ptr, char* file, int line) {
395
traceEvent(TRACE_WARNING, "free(%x) [%s] @ %s:%d", ptr,
396
formatBytes(allocatedMemory, 0), file, line);
398
myFree(ptr, line, file);
401
/* ****************************************** */
403
#else /* MEMORY_DEBUG */
405
/* ****************************************** */
407
#undef malloc /* just to be safe */
408
void* ntop_safemalloc(unsigned int sz, char* file, int line) {
412
if((sz == 0) || (sz > 32768)) {
413
traceEvent(TRACE_WARNING, "WARNING: called malloc(%u) @ %s:%d",
419
memset(thePtr, 0xee, sz); /* Fill it with garbage */
423
/* ****************************************** */
425
/* Courtesy of Wies-Software <wies@wiessoft.de> */
426
#undef calloc /* just to be safe */
427
void* ntop_safecalloc(unsigned int c, unsigned int sz, char* file, int line) {
431
if((sz == 0) || (sz > 32768)) {
432
traceEvent(TRACE_WARNING, "WARNING: called calloc(%u,%u) @ %s:%d",
437
thePtr = calloc(c, sz);
441
/* ****************************************** */
443
/* Courtesy of Wies-Software <wies@wiessoft.de> */
444
#undef realloc /* just to be safe */
445
void* ntop_saferealloc(void* ptr, unsigned int sz, char* file, int line) {
449
if((sz == 0) || (sz > 32768)) {
450
traceEvent(TRACE_WARNING, "WARNING: called realloc(%p,%u) @ %s:%d",
451
ptr, sz, file, line);
455
thePtr = realloc(ptr, sz);
459
/* ****************************************** */
461
#undef free /* just to be safe */
462
void ntop_safefree(void **ptr, char* file, int line) {
464
if((ptr == NULL) || (*ptr == NULL)) {
465
traceEvent(TRACE_WARNING, "WARNING: free of NULL pointer @ %s:%d",
473
#endif /* MEMORY_DEBUG */