summaryrefslogtreecommitdiff
path: root/gs/base/memento.c
diff options
context:
space:
mode:
Diffstat (limited to 'gs/base/memento.c')
-rw-r--r--gs/base/memento.c93
1 files changed, 88 insertions, 5 deletions
diff --git a/gs/base/memento.c b/gs/base/memento.c
index 22ac5e5a2..44b088057 100644
--- a/gs/base/memento.c
+++ b/gs/base/memento.c
@@ -95,7 +95,9 @@ enum {
enum {
Memento_Flag_OldBlock = 1,
- Memento_Flag_HasParent = 2
+ Memento_Flag_HasParent = 2,
+ Memento_Flag_BreakOnFree = 4,
+ Memento_Flag_BreakOnRealloc = 8
};
/* When we list leaked blocks at the end of execution, we search for pointers
@@ -541,7 +543,7 @@ int Memento_listBlocksNested(void)
b->flags &= ~Memento_Flag_HasParent;
b->child = NULL;
b->sibling = NULL;
- b->parent = NULL;
+ b->parent = NULL;
}
qsort(blocks, count, sizeof(void *), ptrcmp);
@@ -562,11 +564,11 @@ int Memento_listBlocksNested(void)
if (r) {
/* Found child */
Memento_BlkHeader *child = MEMBLK_FROMBLK(*r);
- Memento_BlkHeader *parent;
+ Memento_BlkHeader *parent;
/* We're assuming tree structure, not graph - ignore second
* and subsequent pointers. */
- if (child->parent != NULL)
+ if (child->parent != NULL)
continue;
if (child->flags & Memento_Flag_HasParent)
continue;
@@ -581,7 +583,7 @@ int Memento_listBlocksNested(void)
child->sibling = b->child;
b->child = child;
- child->parent = b;
+ child->parent = b;
child->flags |= Memento_Flag_HasParent;
}
}
@@ -1029,6 +1031,9 @@ void Memento_free(void *blk)
if (checkBlock(memblk, "free"))
return;
+ if (memblk->flags & Memento_Flag_BreakOnFree)
+ Memento_breakpoint();
+
VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk));
globals.alloc -= memblk->rawsize;
globals.numFrees++;
@@ -1068,6 +1073,9 @@ void *Memento_realloc(void *blk, size_t newsize)
if (checkBlock(memblk, "realloc"))
return NULL;
+ if (memblk->flags & Memento_Flag_BreakOnRealloc)
+ Memento_breakpoint();
+
if (globals.maxMemory != 0 && globals.alloc - memblk->rawsize + newsize > globals.maxMemory)
return NULL;
@@ -1085,6 +1093,7 @@ void *Memento_realloc(void *blk, size_t newsize)
globals.alloc += newsize;
if (globals.peakAlloc < globals.alloc)
globals.peakAlloc = globals.alloc;
+ newmemblk->flags = memblk->flags;
if (newmemblk->rawsize < newsize) {
char *newbytes = ((char *)MEMBLK_TOBLK(newmemblk))+newmemblk->rawsize;
#ifndef MEMENTO_LEAKONLY
@@ -1296,6 +1305,72 @@ int Memento_find(void *a)
return 0;
}
+void Memento_breakOnFree(void *a)
+{
+ findBlkData data;
+
+ data.addr = a;
+ data.blk = NULL;
+ data.flags = 0;
+ Memento_appBlocks(&globals.used, Memento_containsAddr, &data);
+ if (data.blk != NULL) {
+ fprintf(stderr, "Will stop when address 0x%p (in %sallocated block ",
+ data.addr,
+ (data.flags == 1 ? "" : (data.flags == 2 ?
+ "preguard of " : "postguard of ")));
+ showBlock(data.blk, ' ');
+ fprintf(stderr, ") is freed\n");
+ data.blk->flags |= Memento_Flag_BreakOnFree;
+ return;
+ }
+ data.blk = NULL;
+ data.flags = 0;
+ Memento_appBlocks(&globals.free, Memento_containsAddr, &data);
+ if (data.blk != NULL) {
+ fprintf(stderr, "Can't stop on free; address 0x%p is in %sfreed block ",
+ data.addr,
+ (data.flags == 1 ? "" : (data.flags == 2 ?
+ "preguard of " : "postguard of ")));
+ showBlock(data.blk, ' ');
+ fprintf(stderr, "\n");
+ return;
+ }
+ fprintf(stderr, "Can't stop on free; address 0x%p is not in a known block.\n");
+}
+
+void Memento_breakOnRealloc(void *a)
+{
+ findBlkData data;
+
+ data.addr = a;
+ data.blk = NULL;
+ data.flags = 0;
+ Memento_appBlocks(&globals.used, Memento_containsAddr, &data);
+ if (data.blk != NULL) {
+ fprintf(stderr, "Will stop when address 0x%p (in %sallocated block ",
+ data.addr,
+ (data.flags == 1 ? "" : (data.flags == 2 ?
+ "preguard of " : "postguard of ")));
+ showBlock(data.blk, ' ');
+ fprintf(stderr, ") is freed (or realloced)\n");
+ data.blk->flags |= Memento_Flag_BreakOnFree | Memento_Flag_BreakOnRealloc;
+ return;
+ }
+ data.blk = NULL;
+ data.flags = 0;
+ Memento_appBlocks(&globals.free, Memento_containsAddr, &data);
+ if (data.blk != NULL) {
+ fprintf(stderr, "Can't stop on free/realloc; address 0x%p is in %sfreed block ",
+ data.addr,
+ (data.flags == 1 ? "" : (data.flags == 2 ?
+ "preguard of " : "postguard of ")));
+ showBlock(data.blk, ' ');
+ fprintf(stderr, "\n");
+ return;
+ }
+ fprintf(stderr, "Can't stop on free/realloc; address 0x%p is not in a known block.\n");
+}
+
int Memento_failAt(int i)
{
globals.failAt = i;
@@ -1363,6 +1438,14 @@ int (Memento_failAt)(int i)
return 0;
}
+void (Memento_breakOnFree)(void *a)
+{
+}
+
+void (Memento_breakOnRealloc)(void *a)
+{
+}
+
#undef Memento_malloc
#undef Memento_free
#undef Memento_realloc