summaryrefslogtreecommitdiffstats
path: root/ext/tarkin/mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/tarkin/mem.c')
-rw-r--r--ext/tarkin/mem.c143
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
+