]> git.mdlowis.com Git - projs/libcds.git/commitdiff
leak detector implementation
authorMichael D. Lowis <mike@mdlowis.com>
Tue, 12 Aug 2014 02:23:10 +0000 (22:23 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Tue, 12 Aug 2014 02:23:10 +0000 (22:23 -0400)
source/mem/mem.c
source/mem/mem.h

index c2eb7e658838d880b09784900837b596c0f32702..0d92d31d46d7157a2d0f4868b22fd4092bada6e3 100644 (file)
@@ -1,5 +1,6 @@
 #include "mem.h"
 #include <stdlib.h>
+#include <stdbool.h>
 
 typedef struct {
     int refcount;
@@ -10,6 +11,10 @@ typedef struct {
     intptr_t val;
 } box_t;
 
+#ifndef NDEBUG
+#undef mem_allocate
+#endif
+
 void* mem_allocate(size_t size, destructor_t p_destruct_fn)
 {
     obj_t* p_obj = (obj_t*)malloc(sizeof(obj_t) + size);
@@ -18,18 +23,100 @@ void* mem_allocate(size_t size, destructor_t p_destruct_fn)
     return (void*)(p_obj+1);
 }
 
+#ifndef NDEBUG
+typedef struct block_t {
+    void* p_obj;
+    const char* p_file;
+    int line;
+    struct block_t* p_next;
+} block_t;
+
+block_t* Live_Blocks = NULL;
+bool Handler_Registered = false;
+
+#include <stdio.h>
+static void print_live_objects(void) {
+    bool leak_detected = false;
+    block_t* p_curr = Live_Blocks;
+    while (NULL != p_curr)
+    {
+        block_t* to_be_freed = p_curr;
+        printf("%#x %s (line %d): %d references to object\n",
+               (unsigned int)p_curr->p_obj,
+               p_curr->p_file,
+               p_curr->line,
+               mem_num_references(p_curr->p_obj));
+        p_curr = p_curr->p_next;
+        free(to_be_freed);
+        leak_detected = true;
+    }
+    if(leak_detected)
+        puts("Memory leak(s) detected!");
+}
+
+void* mem_allocate_ld(size_t size, destructor_t p_destruct_fn, const char* p_file, int line)
+{
+    void* p_obj = mem_allocate(size, p_destruct_fn);
+    block_t* p_block = (block_t*)malloc(sizeof(block_t));
+    p_block->p_obj  = p_obj;
+    p_block->p_file = p_file;
+    p_block->line   = line;
+    p_block->p_next = Live_Blocks;
+    Live_Blocks     = p_block;
+    if(!Handler_Registered)
+    {
+        atexit(print_live_objects);
+        Handler_Registered = true;
+    }
+    return p_obj;
+}
+#endif
+
 void mem_retain(void* p_obj)
 {
     obj_t* p_hdr = (((obj_t*)p_obj)-1);
     p_hdr->refcount += 1;
 }
 
+#ifndef NDEBUG
+static void deregister_block(void* p_obj)
+{
+    block_t* p_prev = NULL;
+    block_t* p_curr = Live_Blocks;
+    while((NULL != p_curr) && (NULL != p_curr->p_next))
+    {
+        if (p_obj == p_curr->p_obj)
+        {
+            block_t* p_doomed = p_curr;
+            if(p_prev == NULL)
+            {
+                Live_Blocks = p_curr->p_next;
+            }
+            else
+            {
+                p_prev->p_next = p_curr->p_next;
+            }
+            free(p_doomed);
+            break;
+        }
+        else
+        {
+            p_prev = p_curr;
+            p_curr = p_curr->p_next;
+        }
+    }
+}
+#endif
+
 void mem_release(void* p_obj)
 {
     obj_t* p_hdr = (((obj_t*)p_obj)-1);
     p_hdr->refcount -= 1;
     if(p_hdr->refcount < 1)
     {
+        #ifndef NDEBUG
+        deregister_block(p_obj);
+        #endif
         if(p_hdr->p_finalize)
         {
             p_hdr->p_finalize(p_obj);
index 80534ab0f9ecf9aaacd292a4ce44509517ca12b9..2b9b2e2d9ae1b7a0f604dd7aa65290be18e556aa 100644 (file)
@@ -17,6 +17,7 @@ extern "C" {
 /** A function pointer for object destructors */
 typedef void (*destructor_t)(void* p_val);
 
+#ifdef NDEBUG
 /**
  * @brief Allocates a new reference counted object of the given size which will
  *        be destructed with the given function before it's memory is reclaimed.
@@ -27,6 +28,12 @@ typedef void (*destructor_t)(void* p_val);
  * @return Pointer to the newly allocated object
  */
 void* mem_allocate(size_t size, destructor_t p_destruct_fn);
+#else
+#define mem_allocate(size,destructor) \
+    mem_allocate_ld(size, destructor, __FILE__, __LINE__)
+
+void* mem_allocate_ld(size_t size, destructor_t p_destruct_fn, const char* p_file, int line);
+#endif
 
 /**
  * @brief Returns the reference count for the given object.