Exception Handling and Resource Management

C++ exceptions present a significant challenge to memory and resource management. Normally, when you allocate memory on the heap (free store), you receive a pointer. When you are finished with that memory, you call delete() on the pointer and the memory is returned to the heap.

If your method throws an exception after the memory is allocated, but before the memory is restored, you will create a memory leak. The exception immediately exits the function and the pointer is never deleted. This greatly simplified example illustrates the issue:

#include <iostream.h>

class test
{
public:
   test():myVariable(5) 
   { 
      cout << "test constructor, allocating memory for "
                     "myVariable.\n"; 
      }
   ~test() 
   { 
      cout << "test destructor, memory restored!\n"; 
   }

private:
   int myVariable;
};

class myException
{
};

void SomeFunction();

int main()
{
   try
   {
      SomeFunction();
   }
   catch (...)
   {
      cout << "Caught exception! Not much I can do now to "
                     "clean up the memory.\n";
      return 0;
   }
   cout << "Completed SomeFunction.\n";
   return 0;
};

void SomeFunction()
{
   for (int i = 0; i < 5; i++)
   {
      test* pTest = new test; // create and initialize

      if (i == 4)
         throw new myException;

      delete pTest;
   }
}

The output from this code is as follows:

test constructor, allocating memory for myVariable.

test destructor, memory restored!

test constructor, allocating memory for myVariable.

test destructor, memory restored!

test constructor, allocating memory for myVariable.

test destructor, memory restored!

test constructor, allocating memory for myVariable.

test destructor, memory restored!

test constructor, allocating memory for myVariable.

Caught exception! Not much I can do now to clean up the memory.

The main() method calls SomeFunction() within a try block. SomeFunction() consists of a loop in which memory is allocated and deleted. On the fifth iteration, an exception is thrown. The output reflects that this allocated memory is never restored.

In large complex systems, this can represent a significant threat to the integrity of the system. When an exception is thrown, the stack is unwound and any variables on the stack will be destroyed. Memory allocated on the heap can not be tracked, however. Since C++ does not provide garbage collection, this memory is lost to the system until the program ends.

The reason that the objects pointed to by pointers are not destroyed by the exception mechanism is exactly the same reason that C++ does not have garbage collection — there is tremendous overhead (and thus a significant performance penalty) in tracking this memory. Languages providing these services produce programs that typically run more slowly than those produced by C++.

© 1998 by Wrox Press. All rights reserved.