From: TJ Date: Fri, 8 Apr 2016 19:51:03 +0000 (+0100) Subject: add heap_reap memory manager X-Git-Tag: v1.00~10 X-Git-Url: https://iam.tj/gitweb/gitweb.cgi?p=firmware_extractor.git;a=commitdiff_plain;h=471193f5356782a85ea6378fd4355db97930d122 add heap_reap memory manager --- diff --git a/heap_reap.c b/heap_reap.c new file mode 100644 index 0000000..76f44f8 --- /dev/null +++ b/heap_reap.c @@ -0,0 +1,76 @@ +/* Experimental tracking of heap allocations for easy reaping no matter what the code path is + * Copyright 2016 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 + +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 index 0000000..ebc7074 --- /dev/null +++ b/heap_reap.h @@ -0,0 +1,10 @@ +#ifndef __HEAP_REAP_H +#define __HEAP_REAP_H + +#include +#include + +extern unsigned int heap_debug; +void * heap_and_reap(void *ptr, size_t nmemb, size_t size); + +#endif