When a C++ destructor did not run – Part 1

Consider this piece of C++ code.

   1: using namespace std;


   3: class C

   4: {

   5: public:

   6:     C() 

   7:     { 

   8:         cout << "Constructed"; 

   9:     }

  10:     ~C() 

  11:     { 

  12:         cout << "Destructed"; 

  13:     }

  14: };


  16: void SomeFunc()

  17: {

  18:     C c;

  19:     throw std::exception("Gone");

  20: }

If you know any C++ at all, you’ll know that when SomeFunc returns, both “Constructed” and “Destructed” will be printed to the console. That is because C++ guarantees that the destructor of an object created on the stack will always run when control leaves the scope, no matter what, and RAII depends on that fact.

You put all this code is in a static library, say PureCPP.lib, and you compile it with the /EHs option, because you want to use C++ exceptions.

You then write a native application to consume this library, statically link to it, and everything works great.

One day, you wake up and realize you’ll have to try out this .NET stuff that everyone is talking about. You discover that there’s this language called C++/CLI that’s great for interfacing with native code. So you fire up VS, create a CLR console application that calls SomeFunc, and link PureCPP.lib against it.

Just when you’re wondering how easy things turned out to be, you notice something strange. There’s something missing in the console output. When you figure out what’s missing, your jaw hits the ground. Mine did too, when I realized that it was the “Destructed” part that was missing. Which means the impossible just happened – the destructor for class C did not run.

What followed was a long and exciting journey into the world of SEH (Structured Exception Handling), exception codes and exception propagation and handling by the CLR versus C++. All that in the next part – stay tuned.

Leave a Reply

Your email address will not be published. Required fields are marked *