[PATCH 5/6] apitrace trim: Fix memory leak in CallSet/FastCallSet/FastCallRange objects

Lawrence L Love lawlove at gmail.com
Fri Oct 11 15:05:58 PDT 2013


Assignments of CallSet objects were being made without an overloaded
operator= definition. The CallSet class contains a member variable of
type class FastCallSet which in turn contains a member variable of type
class FastCallRange which allocates memory on construction. An assignment
would overwrite member pointers to allocated memory. Running Valgrind
confirmed this was the case. In addition, there was no destructor defined
to handle the allocated memory for FastCallRange objects.

Added destructor, assignment operator, and copy constructor for FastCallRange.
(Note that copy constructor was unused using "trim" and so is untested)
Added destructor to FastCallSet to cycle through the SkipList.

Signed-off-by: Lawrence L Love <lawrencex.l.love at intel.com>
---
 common/trace_fast_callset.cpp | 95 ++++++++++++++++++++++++++++++++++++++++---
 common/trace_fast_callset.hpp |  6 +++
 2 files changed, 95 insertions(+), 6 deletions(-)

diff --git a/common/trace_fast_callset.cpp b/common/trace_fast_callset.cpp
index 5aebfd2..d583650 100644
--- a/common/trace_fast_callset.cpp
+++ b/common/trace_fast_callset.cpp
@@ -27,8 +27,6 @@
  *
  *********************************************************************/
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <limits>
 
 #include "os.hpp"
@@ -43,10 +41,72 @@ FastCallRange::FastCallRange(CallNo first, CallNo last, int level)
     this->first = first;
     this->last = last;
     this->level = level;
+    this->next = NULL;
 
-    next = new FastCallRange*[level];
+    if (level) {
+        next = new FastCallRange*[level];
+
+        for (int i = 0; i < level; i++)
+            next[i] = NULL;
+    }
 }
 
+// Assignment operator
+FastCallRange & FastCallRange::operator =(const FastCallRange& other)
+{
+    if (this == &other) return *this;
+
+    this->first = other.first;
+    this->last  = other.last;
+
+    if (other.level) {
+        if (this->level != other.level) {
+
+            // Delete this object's memory
+            free_mem();
+
+            // Allocate new memory
+            this->next = new FastCallRange*[other.level];
+
+            this->level = other.level;
+        }
+        // Copy over pointers
+        for (size_t i = 0; i < this->level; i++)
+            this->next[i] = other.next[i];
+    }
+    else {
+        this->next = NULL;
+    }
+
+    return *this;
+} // operator=
+
+// Copy constructor
+FastCallRange::FastCallRange(const FastCallRange& other)
+: first(other.first), last (other.last), level(other.level), next(NULL)
+{
+    if (this->level) {
+        this->next = new FastCallRange*[this->level];
+        
+        for (size_t i = 0; i < this->level; i++)
+            this->next[i] = other.next[i];
+    }
+} // copy constructor
+
+FastCallRange::~FastCallRange()
+{
+    free_mem();
+} // destructor
+
+void
+FastCallRange::free_mem()
+{
+    if (next) {
+        delete [] next;
+        next = NULL;
+    }
+} // free_mem
+
 bool
 FastCallRange::contains(CallNo call_no) const
 {
@@ -64,12 +124,35 @@ FastCallSet::FastCallSet(): head(0, 0, MAX_LEVEL)
     head.first = std::numeric_limits<CallNo>::max();
     head.last = std::numeric_limits<CallNo>::min();
 
-    for (int i = 0; i < MAX_LEVEL; i++)
-        head.next[i] = NULL;
-
     max_level = 0;
 }
 
+FastCallSet::~FastCallSet()
+{
+    rm_node (head.next[0]);
+    delete [] head.next;
+    head.next = NULL;
+    head.level= 0;
+}
+
+void
+FastCallSet::rm_node(FastCallRange * node)
+{
+    if (node) {
+        for (size_t i = 0; i < (node->level); i++) {
+            rm_node (node->next[i]);
+        }
+
+        if (node->next) {
+           delete [] node->next;
+        }
+        node->next = NULL;
+        node->level= 0;
+        delete node;
+        node = NULL;
+    }
+}
+
 /*
  * Generate a random level number, distributed
  * so that each level is 1/4 as likely as the one before
diff --git a/common/trace_fast_callset.hpp b/common/trace_fast_callset.hpp
index af20005..1c2779d 100644
--- a/common/trace_fast_callset.hpp
+++ b/common/trace_fast_callset.hpp
@@ -70,6 +70,10 @@ public:
     FastCallRange **next;
 
     FastCallRange(CallNo first, CallNo last, int level);
+    FastCallRange(const FastCallRange& other); // untested copy constructor
+    FastCallRange & operator =(const FastCallRange& other);
+   ~FastCallRange();
+    void free_mem();
 
     bool contains(CallNo call_no) const;
 };
@@ -80,6 +84,8 @@ public:
     int max_level;
 
     FastCallSet();
+   ~FastCallSet();
+    void rm_node(FastCallRange * node);
 
     bool empty(void) const;
 
-- 
1.8.4.rc3



More information about the apitrace mailing list