Skip to content

Instantly share code, notes, and snippets.

@crimsonwoods
Created April 13, 2013 16:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crimsonwoods/5379148 to your computer and use it in GitHub Desktop.
Save crimsonwoods/5379148 to your computer and use it in GitHub Desktop.
a patch to add memory leak detection.
diff --git src/state.c src/state.c
index 0b6c755..528143e 100644
--- src/state.c
+++ src/state.c
@@ -55,17 +55,124 @@ filename(char const *path)
}
return path;
}
+
+typedef struct alloc_header_t {
+ uint32_t guard;
+ size_t size;
+ char const *file;
+ int line;
+ char const *func;
+} alloc_header_t;
+
+#if defined(MRB_MEMLEAK_DETECTION)
+typedef struct ptr_list_t {
+ void *ptr;
+ struct ptr_list_t *next;
+} ptr_list_t;
+typedef struct ptr_tree_t {
+ ptr_list_t *lists[256][256];
+}ptr_tree_t;
+
+static ptr_tree_t ptr_tree;
+static int volatile ptr_tree_initialized = 0;
+
+static void
+register_ptr(void *ptr) {
+ intptr_t ip = (intptr_t)ptr;
+ if (!ptr_tree_initialized) {
+ memset(&ptr_tree, 0, sizeof(ptr_tree));
+ ptr_tree_initialized = 1;
+ }
+ ptr_list_t *l = ptr_tree.lists[(ip >> 8) & 0xff][(ip >> 16) & 0xff];
+
+ ptr_list_t *new_l = (ptr_list_t*)malloc(sizeof(ptr_list_t));
+ new_l->ptr = ptr;
+ new_l->next = NULL;
+
+ if (NULL == l) {
+ ptr_tree.lists[(ip >> 8) & 0xff][(ip >> 16) & 0xff] = new_l;
+ } else {
+ while (NULL != l->next) {
+ l = l->next;
+ }
+ l->next = new_l;
+ }
+}
+static void
+unregister_ptr(void *ptr) {
+ intptr_t ip = (intptr_t)ptr;
+ ptr_list_t *l = ptr_tree.lists[(ip >> 8) & 0xff][(ip >> 16) & 0xff];
+ ptr_list_t *p = l;
+ if (NULL != l) {
+ do {
+ if (ptr == l->ptr) {
+ if (p == l) {
+ ptr_tree.lists[(ip >> 8) & 0xff][(ip >> 16) & 0xff] = l->next;
+ } else {
+ p->next = l->next;
+ }
+ free(l);
+ break;
+ }
+ p = l;
+ l = l->next;
+ } while (NULL != l);
+ }
+}
+static void __attribute__((destructor))
+release_ptr_tree()
+{
+ int i,j;
+ for (i = 0; i < 256; ++i) {
+ for (j = 0; j < 256; ++j) {
+ ptr_list_t *l = ptr_tree.lists[i][j];
+ if (!l) {
+ continue;
+ }
+ do {
+ alloc_header_t const * const hdr = (alloc_header_t*)l->ptr;
+ void *ptr = (uint8_t *)l->ptr + sizeof(alloc_header_t);
+ fprintf(stderr, "LEAK : %10p %8lu %15s %4d (%s)\n", ptr, hdr->size, filename(hdr->file), hdr->line, hdr->func);
+ l = l->next;
+ } while (NULL != l);
+ }
+ }
+}
+#else
+#define register_ptr(ptr)
+#define unregister_ptr(ptr)
+#endif
+
static void*
allocf(mrb_state *mrb, void *p, size_t size, void *ud, char const *file, int line, char const *func)
{
if (size == 0) {
- fprintf(stderr, "FREE : %10p %15s %4d (%s)\n", p, filename(file), line, func);
- free(p);
+ if (NULL != p) {
+ alloc_header_t *hdr = (alloc_header_t *)((uint8_t *)p - sizeof(alloc_header_t));
+ if (hdr->guard != 0xdeadbeef) {
+ fprintf(stderr, "#### DETECT HEAP MEMORY CORRUPTION!!!! ####\n");
+ }
+ fprintf(stderr, "FREE : %10p %8lu %15s %4d (%s)\n", hdr + 1, hdr->size, filename(file), line, func);
+ free(hdr);
+ unregister_ptr(hdr);
+ }
return NULL;
}
else {
- void *new_ptr = realloc(p, size);
+ alloc_header_t *hdr = (NULL == p) ? NULL : (alloc_header_t*)((uint8_t *)p - sizeof(alloc_header_t));
+ void *new_ptr = realloc(hdr, sizeof(alloc_header_t) + size);
if (new_ptr) {
+ alloc_header_t *new_hdr = (alloc_header_t *)new_ptr;
+ if (new_hdr != hdr) {
+ unregister_ptr(hdr);
+ register_ptr(new_hdr);
+ new_hdr->guard = 0xdeadbeef;
+ new_hdr->file = file;
+ new_hdr->line = line;
+ new_hdr->func = func;
+ }
+ new_hdr->size = size;
+ new_ptr = (void*)((uint8_t *)new_ptr) + sizeof(alloc_header_t);
if (NULL == p) {
fprintf(stderr, "ALLOCATE: %10p %8lu %15s %4d (%s)\n", new_ptr, size, filename(file), line, func);
} else {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment