add heap_reap memory manager
authorTJ <hacker@iam.tj>
Fri, 8 Apr 2016 19:51:03 +0000 (20:51 +0100)
committerTJ <hacker@iam.tj>
Fri, 8 Apr 2016 19:51:03 +0000 (20:51 +0100)
heap_reap.c [new file with mode: 0644]
heap_reap.h [new file with mode: 0644]

diff --git a/heap_reap.c b/heap_reap.c
new file mode 100644 (file)
index 0000000..76f44f8
--- /dev/null
@@ -0,0 +1,76 @@
+/* Experimental tracking of heap allocations for easy reaping no matter what the code path is
+ * Copyright 2016 TJ <hacker@iam.tj>
+ * Licensed on the terms of the GNU General Public License version 3.
+ *
+ * Both tasks are in the same function to take advantage of local static variables that are
+ * persistent across calls but invisible to code outside the function.
+ */
+
+#include "heap_reap.h"
+#include <stdio.h>
+
+unsigned int heap_debug = 0;
+
+struct mem_track {
+  void *ptr;
+  struct mem_track *prev;
+  struct mem_track *next;
+  size_t requested;
+  size_t allocated;
+};
+
+/* 
+ * @param ptr   NULL: calloc(nmemb, size), NULL-1: reap all, otherwise free(ptr)
+ * @param nmemb number of elements of size to allocate
+ * @param size  size if each element
+ */
+void *
+heap_and_reap(void *ptr, size_t nmemb, size_t size)
+{
+  static struct mem_track *memalloc = NULL;
+  struct mem_track *tmp;
+  void *result = NULL;
+
+  if (ptr == NULL) { 
+    // allocate requested memory and 'hide' the struct mem_track at the end of it
+    size_t dwords = ((nmemb * size + sizeof(struct mem_track)) / 4) + 1;
+
+    if ((result = calloc(dwords, 4)) != NULL) {
+      tmp = (struct mem_track *) (result + (dwords * 4) - sizeof(struct mem_track)  );
+      tmp->allocated = dwords * 4;
+      tmp->requested = nmemb * size;
+      tmp->ptr = result;
+      tmp->prev = memalloc;
+      tmp->next = NULL;
+      if (memalloc)
+        memalloc->next = tmp;
+      else
+        memalloc = tmp;
+      if (heap_debug)
+        fprintf(stderr, "heap req %08lx alloc %08lx @ %p\n", tmp->requested, tmp->allocated, tmp);
+    }
+  }
+  else { // free allocation
+    struct mem_track *p = memalloc;
+    while (p) {
+      if (ptr == NULL-1 || p->ptr == ptr) { // free all or a specific allocation
+        if (heap_debug)
+          fprintf(stderr, "heap free %08lx @ %p\n", p->allocated, p);
+        tmp = p->next;
+        if (p->prev)
+          p->prev->next = p->next;
+        if (p->next)
+          p->next->prev = p->prev;
+        free(p->ptr);
+        if (memalloc == p)
+          memalloc = tmp;
+        p = tmp;
+        if (ptr != NULL-1) // only freeing a specific allocation
+          break;
+      } else
+        p = p->next;
+    }
+  }
+  return result;
+}
+
diff --git a/heap_reap.h b/heap_reap.h
new file mode 100644 (file)
index 0000000..ebc7074
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __HEAP_REAP_H
+#define __HEAP_REAP_H
+
+#include <stdlib.h>
+#include <sys/types.h>
+
+extern unsigned int heap_debug;
+void * heap_and_reap(void *ptr, size_t nmemb, size_t size);
+
+#endif