/* * Debugging implementation of MALLOC and friends */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #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