diff options
Diffstat (limited to 'ext/tarkin/mem.c')
-rw-r--r-- | ext/tarkin/mem.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/ext/tarkin/mem.c b/ext/tarkin/mem.c new file mode 100644 index 00000000..c2cf18c0 --- /dev/null +++ b/ext/tarkin/mem.c @@ -0,0 +1,143 @@ +/* + * Debugging implementation of MALLOC and friends + */ + + +#include "mem.h" + +#if defined(DBG_MEMLEAKS) + +typedef struct { + void *mem; + char *allocated_in_func; + char *allocated_in_file; + unsigned int allocated_in_line; +} MemDesc; + + +static int initialized = 0; +static int alloc_count = 0; +static MemDesc *alloc_list = NULL; + + +static +void dbg_memleaks_done (int exitcode, void *dummy) +{ + unsigned int i; + (void) dummy; + + if (exitcode == 0 && alloc_count != 0) { + fprintf (stderr, "\nmemory leak detected !!!\n"); + fprintf (stderr, "\nalloc_count == %i\n\n", alloc_count); + for (i=0; i<alloc_count; i++) { + MemDesc *d = &alloc_list[i]; + fprintf (stderr, "chunk %p allocated in %s (%s: %u) not free'd !!\n", + d->mem, d->allocated_in_func, d->allocated_in_file, + d->allocated_in_line); + } + free(alloc_list); + } + fprintf (stderr, "\n"); +} + + +static +void dbg_memleaks_init (void) +{ + on_exit (dbg_memleaks_done, NULL); + initialized = 1; +} + + +void* dbg_malloc (char* file, int line, char *func, size_t bytes) +{ + void *mem = (void*) malloc (bytes); + MemDesc *d; + + if (!initialized) + dbg_memleaks_init(); + + alloc_count++; + alloc_list = realloc (alloc_list, alloc_count * sizeof(MemDesc)); + + d = &alloc_list[alloc_count-1]; + d->mem = mem; + d->allocated_in_func = func; + d->allocated_in_file = file; + d->allocated_in_line = line; + + return mem; +} + + +void* dbg_calloc (char* file, int line, char *func, size_t count, size_t bytes) +{ + void *mem = (void*) calloc (count, bytes); + MemDesc *d; + + if (!initialized) + dbg_memleaks_init(); + + alloc_count++; + alloc_list = realloc (alloc_list, alloc_count * sizeof(MemDesc)); + + d = &alloc_list[alloc_count-1]; + d->mem = mem; + d->allocated_in_func = func; + d->allocated_in_file = file; + d->allocated_in_line = line; + + return mem; +} + + +void* dbg_realloc (char *file, int line, char *func, char *what, + void *mem, size_t bytes) +{ + unsigned int i; + + for (i=0; i<alloc_count; i++) { + if (alloc_list[i].mem == mem) { + alloc_list[i].mem = (void*) realloc (mem, bytes); + return alloc_list[i].mem; + } + } + + if (mem != NULL) { + fprintf (stderr, + "%s: trying to reallocate unknown chunk %p (%s)\n" + " in %s (%s: %u) !!!\n", + __FUNCTION__, mem, what, func, file, line); + exit (-1); + } + + return dbg_malloc(file, line, func, bytes); +} + + +void dbg_free (char *file, int line, char *func, char *what, void *mem) +{ + unsigned int i; + + if (!initialized) + dbg_memleaks_init(); + + for (i=0; i<alloc_count; i++) { + if (alloc_list[i].mem == mem) { + free (mem); + alloc_count--; + memmove (&alloc_list[i], &alloc_list[i+1], + (alloc_count - i) * sizeof(MemDesc)); + return; + } + } + + fprintf (stderr, "%s: trying to free unknown chunk %p (%s)\n" + " in %s (%s: %u) !!!\n", + __FUNCTION__, mem, what, func, file, line); + exit (-1); +} + + +#endif + |