From: José Fonseca <jose.r.fonseca@gmail.com>
Date: Thu, 3 Nov 2011 19:35:53 +0000 (+0000)
Subject: Plug several leaks when retracing.
X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=d994cf0c2c7d198ac3daacfe83a1f6b3c3c9e975;p=apitrace

Plug several leaks when retracing.

Use a scoped allocator to help keep track of the things that need to be
freed.
---

diff --git a/retrace.hpp b/retrace.hpp
index 57b8b05..dc11bb3 100644
--- a/retrace.hpp
+++ b/retrace.hpp
@@ -1,6 +1,6 @@
 /**************************************************************************
  *
- * Copyright 2011 Jose Fonseca
+ * Copyright 2011-2012 Jose Fonseca
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -80,6 +80,53 @@ public:
 };
 
 
+/**
+ * Similar to alloca(), but implemented with malloc.
+ */
+class ScopedAllocator
+{
+private:
+    void *next;
+
+public:
+    ScopedAllocator() :
+        next(NULL) {
+    }
+
+    inline void *
+    alloc(size_t size) {
+        if (!size) {
+            return NULL;
+        }
+
+        void * * buf = static_cast<void **>(malloc(sizeof(void *) + size));
+        if (!buf) {
+            return NULL;
+        }
+
+        *buf = next;
+        next = buf;
+
+        return &buf[1];
+    }
+
+    template< class T >
+    inline T *
+    alloc(size_t n = 1) {
+        return static_cast<T *>(alloc(sizeof(T) * n));
+    }
+
+    inline
+    ~ScopedAllocator() {
+        while (next) {
+            void *temp = *static_cast<void **>(next);
+            free(next);
+            next = temp;
+        }
+    }
+};
+
+
 void
 addRegion(unsigned long long address, void *buffer, unsigned long long size);
 
diff --git a/retrace.py b/retrace.py
index 25e2609..1203a09 100644
--- a/retrace.py
+++ b/retrace.py
@@ -72,7 +72,7 @@ class ValueDeserializer(stdapi.Visitor):
         print '    const trace::Array *__a%s = dynamic_cast<const trace::Array *>(&%s);' % (array.tag, rvalue)
         print '    if (__a%s) {' % (array.tag)
         length = '__a%s->values.size()' % array.tag
-        print '        %s = new %s[%s];' % (lvalue, array.type, length)
+        print '        %s = _allocator.alloc<%s>(%s);' % (lvalue, array.type, length)
         index = '__j' + array.tag
         print '        for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
         try:
@@ -86,7 +86,7 @@ class ValueDeserializer(stdapi.Visitor):
     def visitPointer(self, pointer, lvalue, rvalue):
         print '    const trace::Array *__a%s = dynamic_cast<const trace::Array *>(&%s);' % (pointer.tag, rvalue)
         print '    if (__a%s) {' % (pointer.tag)
-        print '        %s = new %s;' % (lvalue, pointer.type)
+        print '        %s = _allocator.alloc<%s>();' % (lvalue, pointer.type)
         try:
             self.visit(pointer.type, '%s[0]' % (lvalue,), '*__a%s->values[0]' % (pointer.tag,))
         finally:
@@ -212,6 +212,8 @@ class Retracer:
             print '    (void)call;'
             return
 
+        print '    retrace::ScopedAllocator _allocator;'
+        print '    (void)_allocator;'
         success = True
         for arg in function.args:
             arg_type = ConstRemover().visit(arg.type)