2002-02-03 16:30:31 +00:00
|
|
|
/*
|
|
|
|
* Debugging implementation of MALLOC and friends
|
|
|
|
*/
|
|
|
|
|
2003-11-07 12:47:02 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
2002-02-03 16:30:31 +00:00
|
|
|
|
|
|
|
#include "mem.h"
|
|
|
|
|
|
|
|
#if defined(DBG_MEMLEAKS)
|
|
|
|
|
2004-03-14 22:34:33 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
void *mem;
|
|
|
|
char *allocated_in_func;
|
|
|
|
char *allocated_in_file;
|
|
|
|
unsigned int allocated_in_line;
|
2002-02-03 16:30:31 +00:00
|
|
|
} MemDesc;
|
|
|
|
|
|
|
|
|
|
|
|
static int initialized = 0;
|
|
|
|
static int alloc_count = 0;
|
|
|
|
static MemDesc *alloc_list = NULL;
|
|
|
|
|
|
|
|
|
2004-03-14 22:34:33 +00:00
|
|
|
static void
|
|
|
|
dbg_memleaks_done (int exitcode, void *dummy)
|
2002-02-03 16:30:31 +00:00
|
|
|
{
|
2004-03-14 22:34:33 +00:00
|
|
|
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");
|
2002-02-03 16:30:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-14 22:34:33 +00:00
|
|
|
static void
|
|
|
|
dbg_memleaks_init (void)
|
2002-02-03 16:30:31 +00:00
|
|
|
{
|
2004-03-14 22:34:33 +00:00
|
|
|
on_exit (dbg_memleaks_done, NULL);
|
|
|
|
initialized = 1;
|
2002-02-03 16:30:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-14 22:34:33 +00:00
|
|
|
void *
|
|
|
|
dbg_malloc (char *file, int line, char *func, size_t bytes)
|
2002-02-03 16:30:31 +00:00
|
|
|
{
|
2004-03-14 22:34:33 +00:00
|
|
|
void *mem = (void *) malloc (bytes);
|
|
|
|
MemDesc *d;
|
2002-02-03 16:30:31 +00:00
|
|
|
|
2004-03-14 22:34:33 +00:00
|
|
|
if (!initialized)
|
|
|
|
dbg_memleaks_init ();
|
2002-02-03 16:30:31 +00:00
|
|
|
|
2004-03-14 22:34:33 +00:00
|
|
|
alloc_count++;
|
|
|
|
alloc_list = realloc (alloc_list, alloc_count * sizeof (MemDesc));
|
2002-02-03 16:30:31 +00:00
|
|
|
|
2004-03-14 22:34:33 +00:00
|
|
|
d = &alloc_list[alloc_count - 1];
|
|
|
|
d->mem = mem;
|
|
|
|
d->allocated_in_func = func;
|
|
|
|
d->allocated_in_file = file;
|
|
|
|
d->allocated_in_line = line;
|
2002-02-03 16:30:31 +00:00
|
|
|
|
2004-03-14 22:34:33 +00:00
|
|
|
return mem;
|
2002-02-03 16:30:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-14 22:34:33 +00:00
|
|
|
void *
|
|
|
|
dbg_calloc (char *file, int line, char *func, size_t count, size_t bytes)
|
2002-02-03 16:30:31 +00:00
|
|
|
{
|
2004-03-14 22:34:33 +00:00
|
|
|
void *mem = (void *) calloc (count, bytes);
|
|
|
|
MemDesc *d;
|
2002-02-03 16:30:31 +00:00
|
|
|
|
2004-03-14 22:34:33 +00:00
|
|
|
if (!initialized)
|
|
|
|
dbg_memleaks_init ();
|
2002-02-03 16:30:31 +00:00
|
|
|
|
2004-03-14 22:34:33 +00:00
|
|
|
alloc_count++;
|
|
|
|
alloc_list = realloc (alloc_list, alloc_count * sizeof (MemDesc));
|
2002-02-03 16:30:31 +00:00
|
|
|
|
2004-03-14 22:34:33 +00:00
|
|
|
d = &alloc_list[alloc_count - 1];
|
|
|
|
d->mem = mem;
|
|
|
|
d->allocated_in_func = func;
|
|
|
|
d->allocated_in_file = file;
|
|
|
|
d->allocated_in_line = line;
|
2002-02-03 16:30:31 +00:00
|
|
|
|
2004-03-14 22:34:33 +00:00
|
|
|
return mem;
|
2002-02-03 16:30:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-14 22:34:33 +00:00
|
|
|
void *
|
|
|
|
dbg_realloc (char *file, int line, char *func, char *what,
|
|
|
|
void *mem, size_t bytes)
|
2002-02-03 16:30:31 +00:00
|
|
|
{
|
2004-03-14 22:34:33 +00:00
|
|
|
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);
|
2002-02-03 16:30:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-14 22:34:33 +00:00
|
|
|
void
|
|
|
|
dbg_free (char *file, int line, char *func, char *what, void *mem)
|
2002-02-03 16:30:31 +00:00
|
|
|
{
|
2004-03-14 22:34:33 +00:00
|
|
|
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);
|
2002-02-03 16:30:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|