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

Reply via email to