Why destructor is not called on exception?

C++ExceptionVisual C++DestructorStack Unwinding

C++ Problem Overview


I expected A::~A() to be called in this program, but it isn't:

#include <iostream>

struct A {
  ~A() { std::cout << "~A()" << std::endl; }
};

void f() {
  A a;
  throw "spam";
}

int main() { f(); }

However, if I change last line to

int main() try { f(); } catch (...) { throw; }

then A::~A() is called.

I am compiling with "Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86" from Visual Studio 2005. Command line is cl /EHa my.cpp.

Is compiler right as usual? What does standard say on this matter?

C++ Solutions


Solution 1 - C++

The destructor is not being called because terminate() for the unhandled exception is called before the stack gets unwound.

The specific details of what the C++ spec says is outside of my knowledge, but a debug trace with gdb and g++ seems to bear this out.

According to the draft standard section 15.3 bullet 9:

9 If no matching handler is found in a program, the function terminate()
(except.terminate)  is  called.  Whether or not the stack is unwound
before calling terminate() is implementation-defined.

Solution 2 - C++

C++ language specification states: The process of calling destructors for automatic objects constructed on the path from a try block to a throw-expression is called “stack unwinding.” Your original code does not contain try block, that is why stack unwinding does not happen.

Solution 3 - C++

Sorry I don't have a copy of the standard on me.
I would definitely like a definitive answer to this, so somebody with copy of the standard want to share chapter and verse on whats happening:

From my understanding terminate is only called iff:

  • The exception handling mechanism cannot find a handler for a thrown exception.
    The following are more specific cases of this:
  • During stack unwinding, an exception escapes a destructor.
  • An thrown expression, an exception escapes the constructor.
  • An exception escapes the constructor/destructor of a non local static (ie global)
  • An exception escapes a function registered with atexit().
  • An exception escapes main()
  • Trying to re-throw an exception when no exception is currently propagating.
  • An unexpected exception escapes a function with exception specifiers (via unexpected)

Solution 4 - C++

In the second example, the dtor is called when it leaves the try{} block.

In the first example, the dtor is called as the program shuts down after leaving the main() function --- by which time cout may already have been destroyed.

Solution 5 - C++

I assumed too that the compiler don't generate the code relative to "a" as it's not referenced but still, it's not the right behavior as the destructor does something that have to be executed.

So, i tried in VS2008/vc9 (+SP1), Debug and Release and ~A is called after the exception is thrown, getting out of f() - that is the right behavior, if i'm right.

Now i just tried with VS2005/vc8 (+SP1) and it's the same behavior.

I used breakpoints to be sure. I just checked with the console and i have the "~A" message too. Maybe you did it wrong somewhere else?

Solution 6 - C++

This question is easy to google so I share my situation here.

Make sure yor exeption does not cross extern "C" boundary or use MSVC option /EHs (Enable C++ exeptions = Yes with Extern C functions (/EHs))

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionConstantinView Question on Stackoverflow
Solution 1 - C++lefticusView Answer on Stackoverflow
Solution 2 - C++Alex CheView Answer on Stackoverflow
Solution 3 - C++Martin YorkView Answer on Stackoverflow
Solution 4 - C++James CurranView Answer on Stackoverflow
Solution 5 - C++KlaimView Answer on Stackoverflow
Solution 6 - C++light_keeperView Answer on Stackoverflow