about summary refs log tree commit diff
path: root/src/rt
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-09-06 14:15:01 -0700
committerPatrick Walton <pcwalton@mimiga.net>2011-09-06 14:15:01 -0700
commitd3e8887d3c7ecbfacb0e1693b1a0b8164461d6e0 (patch)
treec41e086f5d74a420e0a85c860ba0a75532a1b62f /src/rt
parent23210a3293d34822579d8a58b043694286595daf (diff)
downloadrust-d3e8887d3c7ecbfacb0e1693b1a0b8164461d6e0.tar.gz
rust-d3e8887d3c7ecbfacb0e1693b1a0b8164461d6e0.zip
rt: Implement poison-on-free, for debugging memory issues
Diffstat (limited to 'src/rt')
-rw-r--r--src/rt/memory_region.cpp20
-rw-r--r--src/rt/memory_region.h4
2 files changed, 23 insertions, 1 deletions
diff --git a/src/rt/memory_region.cpp b/src/rt/memory_region.cpp
index 1527addb0f6..ef8a92b427f 100644
--- a/src/rt/memory_region.cpp
+++ b/src/rt/memory_region.cpp
@@ -43,6 +43,7 @@ void memory_region::free(void *mem) {
         _srv->fatal("live_allocs < 1", __FILE__, __LINE__, "");
     }
     release_alloc(mem);
+    maybe_poison(mem);
     _srv->free(alloc);
 }
 
@@ -52,9 +53,11 @@ memory_region::realloc(void *mem, size_t size) {
     if (!mem) {
         add_alloc();
     }
+    size_t old_size = size;
     size += sizeof(alloc_header);
     alloc_header *alloc = get_header(mem);
     assert(alloc->magic == MAGIC);
+    alloc->size = old_size;
     alloc_header *newMem = (alloc_header *)_srv->realloc(alloc, size);
 #ifdef TRACK_ALLOCATIONS
     if (_allocation_list[newMem->index] != alloc) {
@@ -82,6 +85,7 @@ memory_region::malloc(size_t size, const char *tag, bool zero) {
     mem->magic = MAGIC;
     mem->tag = tag;
     mem->index = -1;
+    mem->size = old_size;
     claim_alloc(mem->data);
 
     if(zero) {
@@ -169,6 +173,22 @@ memory_region::claim_alloc(void *mem) {
     add_alloc();
 }
 
+void
+memory_region::maybe_poison(void *mem) {
+    // TODO: We should lock this, in case the compiler doesn't.
+    static int poison = -1;
+    if (poison < 0) {
+        char *env_str = getenv("RUST_POISON_ON_FREE");
+        poison = env_str != NULL && env_str[0] != '\0';
+    }
+
+    if (!poison)
+        return;
+
+    alloc_header *alloc = get_header(mem);
+    memset(mem, '\xcd', alloc->size);
+}
+
 //
 // Local Variables:
 // mode: C++
diff --git a/src/rt/memory_region.h b/src/rt/memory_region.h
index 26a21f45028..0197057268c 100644
--- a/src/rt/memory_region.h
+++ b/src/rt/memory_region.h
@@ -19,7 +19,7 @@ private:
         uint32_t magic;
         int index;
         const char *tag;
-        uint32_t pad;       // To stay 16 byte aligned.
+        uint32_t size;
         char data[];
     };
 
@@ -36,6 +36,8 @@ private:
 
     void add_alloc();
     void dec_alloc();
+    void maybe_poison(void *mem);
+
 public:
     memory_region(rust_srv *srv, bool synchronized);
     memory_region(memory_region *parent);