1 /* Experimental tracking of heap allocations for easy reaping no matter what the code path is
2 * Copyright 2016 TJ <hacker@iam.tj>
3 * Licensed on the terms of the GNU General Public License version 3.
5 * Both tasks are in the same function to take advantage of local static variables that are
6 * persistent across calls but invisible to code outside the function.
12 unsigned int heap_debug = 0;
16 struct mem_track *prev;
17 struct mem_track *next;
23 * @param ptr NULL: calloc(nmemb, size), NULL-1: reap all, otherwise free(ptr)
24 * @param nmemb number of elements of size to allocate
25 * @param size size if each element
28 heap_and_reap(void *ptr, size_t nmemb, size_t size)
30 static struct mem_track *memalloc = NULL;
31 struct mem_track *tmp;
35 // allocate requested memory and 'hide' the struct mem_track at the end of it
36 size_t dwords = ((nmemb * size + sizeof(struct mem_track)) / 4) + 1;
38 if ((result = calloc(dwords, 4)) != NULL) {
39 tmp = (struct mem_track *) (result + (dwords * 4) - sizeof(struct mem_track) );
40 tmp->allocated = dwords * 4;
41 tmp->requested = nmemb * size;
44 tmp->next = memalloc ? memalloc->next : NULL;
47 memalloc->next->prev = tmp;
53 fprintf(stderr, "heap %p req %08lx alloc %08lx @ %p track %p next %p\n", memalloc, tmp->requested, tmp->allocated, tmp->ptr, tmp, memalloc->next);
56 else { // free allocation
57 struct mem_track *p = memalloc;
60 fprintf(stderr, "%sheap %p free %08lx @ %p track %p next %p\n", (p->ptr != ptr ? " " : ""), memalloc, p->requested, p->ptr, p, p->next);
61 if (ptr == NULL-1 || p->ptr == ptr) { // free all or a specific allocation
64 p->prev->next = p->next;
66 p->next->prev = p->prev;
71 if (ptr != NULL-1) // only freeing a specific allocation