a few notes on memory leaks


Subject: a few notes on memory leaks
From: Tomas Frydrych (tomas@frydrych.uklinux.net)
Date: Wed Jan 30 2002 - 10:51:54 CST


I have been making my way through tracking down and fixing
memory leaks in AW, and there are few observations that are
perhaps worth sharing:

(1) vast majority of the memory leaks are connected to using
UT_strdup; when duplicating strings, we need to make sure that we
know where and when the string gets freed. This is particularly
important when passing the pointer to a duplicated string
somewhere else (i.e. inserting it to hashes, vectors, etc.).

(2) we should not mix pointers that need to be freed and pointers
that should not in a single array that we pass onto someone else,
something like:

  char ** my_function()
  {
    char str1[] = "string";
    char * str2 = UT_strdup(str1);
    char ** arrray = new char*[2];
    array[0] = str1; array[1] = str2;
    return array;
  }

This virtually guarantees a memory leak since the caller has no
way of knowing how to free the memory used by array (if pointers
to data that needs different disposal mechanism is to be combined
together, it is best to design a class with a destructor that knows
how to handle the disposal).

(3) When designing new classes, as a rule we should include a
virtual destructor _even if_ there is nothing in the class that needs
destroying; if not we will get memory leaks when freeing pointers to
derived classes without explicit cast, e.g.,

class my_class {
        public: // no costructor or destructor
...
};

class my_derrived_class : my_class {
        public:
         my_derrived_class();
            virtual ~my_derrived_class(){};
        private:
            UT_String str;
};

my_class * my_class_ptr = new my_derrived_class();
delete my_class_ptr;

In this case the destructor of my_derrived_class does not get
called, because my_class does not have a virtual destructor. The
fact that the base class and the derrived classes do not need any
special action to be taken in the destructor, does not mean that we
need not to have a virtual destructor; in the example above, the
destructor of the UT_String class, which would be called implicitely
when destroying object of type my_derrived_class, will not be
called and we will get a memory leak which is hard to track down
because the actual code looks just fine.

Tomas



This archive was generated by hypermail 2b25 : Wed Jan 30 2002 - 10:53:25 CST