From 31c0b0c7e1e9340145e11866c74e20ceddae77f9 Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Sun, 26 Apr 2015 21:19:40 -0400 Subject: zone: Add -zonescan parameter. As further tooling to help debug bugs like #530, add a command line parameter that will scan the zone heap every time a block of memory is freed with Z_Free(), to detect dangling pointers to the freed block. --- src/z_zone.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/src/z_zone.c b/src/z_zone.c index 91f31fb2..311eff50 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -64,6 +64,7 @@ typedef struct static memzone_t *mainzone; static boolean zero_on_free; +static boolean scan_on_free; // @@ -120,12 +121,54 @@ void Z_Init (void) block->size = mainzone->size - sizeof(memzone_t); //! - // Zone memory debugging flag. If set, zero memory after it is freed + // Zone memory debugging flag. If set, memory is zeroed after it is freed // to deliberately break any code that attempts to use it after free. // zero_on_free = M_ParmExists("-zonezero"); + + //! + // Zone memory debugging flag. If set, each time memory is freed, the zone + // heap is scanned to look for remaining pointers to the freed block. + // + scan_on_free = M_ParmExists("-zonescan"); } +// Scan the zone heap for pointers within the specified range, and warn about +// any remaining pointers. +static void ScanForBlock(void *start, void *end) +{ + memblock_t *block; + void **mem; + int i, len, tag; + + block = mainzone->blocklist.next; + + while (block->next != &mainzone->blocklist) + { + tag = block->tag; + + if (tag == PU_STATIC || tag == PU_LEVEL || tag == PU_LEVSPEC) + { + // Scan for pointers on the assumption that pointers are aligned + // on word boundaries (word size depending on pointer size): + mem = (void **) ((byte *) block + sizeof(memblock_t)); + len = (block->size - sizeof(memblock_t)) / sizeof(void *); + + for (i = 0; i < len; ++i) + { + if (start <= mem[i] && mem[i] <= end) + { + fprintf(stderr, + "%p has dangling pointer into freed block " + "%p (%p -> %p)\n", + mem, start, &mem[i], mem[i]); + } + } + } + + block = block->next; + } +} // // Z_Free @@ -157,6 +200,11 @@ void Z_Free (void* ptr) { memset(ptr, 0, block->size - sizeof(memblock_t)); } + if (scan_on_free) + { + ScanForBlock(ptr, + (byte *) ptr + block->size - sizeof(memblock_t)); + } other = block->prev; -- cgit v1.2.3