Destructors instead of catches

Sunday 15 February 2004This is over 19 years old. Be careful.

One of the most powerful features of C++ is that stack objects are guaranteed to be destroyed as functions are exited, regardless of why they were exited (normal return, or an exception being thrown). This is one of those clever techniques that is easy to know about, but then easy to overlook anyway (as I recently did). I’ve written an article about it: Destructors instead of catches.


One aspect of C++ exceptions and destructors is worth highlighting: Do not let your destructors throw exceptions. This is good general advice but specifically when destructors are called during stack unwind, you need to make sure that exceptions aren't thrown. If a destructor throws an exception while another exception is being processed, then a function called terminate() is called, which causes the program to go away. Not a good thing.

Exceptions may be unavoidable in code that's called by a destructor -- the important thing is that the destructor does not allow them to propagate through it. You may need to resort to a catch (...) { } block if you're paranoid -- you should try to keep your destructors as simple as possible.
Another related comment: in your article you say that C++ guarantess that an object's destructor will be called when the function exits. While that's true, it's a little more complicated than that. Objects declared locally are block scoped. So the destructor is called when the block is left. There was heated debate when the C++ Standard was being finalized. Earlier C++ specs weren't really specific as to when destructors were called for variables defined in block scope. It was more or less left up to the vendor. Some compilers generated code where destructors weren't called until the function exited. I believe that the standard is clear about this now. The tricky aspect for a compiler writer to get the proper behavior in the face of random gotos in code that enter or leave blocks. Sure, noone should code this way but the language allows it so the compiler has to do something intelligent.

Why does this matter? Well, if you define a Resource allocator in one block in a function and then have another block further down that does the same thing, has the destructor for the first resource been released yet? If the answer is vendor-specific then your code would need to be broken up into separate functions/methods to work properly everywhere. Also, some people are crazy enough to have nested exception handling in functions/methods. Destructor behavior needs to work properly here too.

By the way, are the comments on the blog entry separate from the comments on the article? Should I be putting my comments there instead?

Add a comment:

Ignore this:
Leave this empty:
Name is required. Either email or web are required. Email won't be displayed and I won't spam you. Your web site won't be indexed by search engines.
Don't put anything here:
Leave this empty:
Comment text is Markdown.