Why is the destructor not caused by an exception?

I expected A::~A() be called in this program, but it is not:

 #include <iostream> struct A { ~A() { std::cout << "~A()" << std::endl; } }; void f() { A a; throw "spam"; } int main() { f(); } 

However, if I change the last line to

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

then A::~A() is called.

I am compiling with a 32-bit 32-bit C ++ compiler for the Microsoft (R) 14.00.50727.762 for 80x86 "compiler from Visual Studio 2005. The command line is cl /EHa my.cpp .

Does the compiler work correctly? What does the standard say on this?

+43
c ++ exception destructor visual-c ++ stack-unwinding
Oct 21 '08 at 14:52
source share
6 answers

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

The specific details of what the C ++ spec says are beyond my knowledge, but the debug trace with gdb and g ++ seems to confirm this.

According to the draft draft in 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.
+61
Oct. 21 '08 at 15:04
source share

C ++ language specification: The process of calling destructors for automatic objects built along the path from a try block to a throw expression is called "stack expansion". The source code does not contain a try block, so the stack does not expand.

+13
Oct 22 '08 at 12:19
source share

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

In the first example, dtor is called when the program shuts down after exiting the main () function --- by then, cout may already be destroyed.

+2
Oct 21 '08 at 14:58
source share

I also suggested that the compiler does not generate code relative to "a" since it does not reference, but still, this is not the correct behavior, because the destructor does something that needs to be executed.

So, I tried in VS2008 / vc9 (+ SP1), Debug and Release and ~ A is called after the exception is thrown, exiting f () - this is the correct behavior, if I am right.

Now I just tried with VS2005 / vc8 (+ SP1), and this is the same behavior.

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

+2
Oct 21 '08 at 15:02
source share

This question is easy for Google, so I share my situation here.

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

+2
May 11 '16 at 1:52 pm
source share

Sorry, I do not have a copy of the standard on me.
I would definitely like to give a definitive answer to this question, so someone with a copy of the standard will want to share a chapter and a verse about what is happening:

From my understanding of terminate, only iff is called:

  • The exception handling engine cannot find a handler for the generated exception.
    The following are more specific cases:
    • During stack unwinding, an exception exits from the destructor.
    • An abandoned expression, an exception throws a constructor.
    • An exception throws a constructor / destructor of a non-local static (i.e. global)
    • An exception throws a function registered with atexit ().
    • Exception throws main ()
  • An attempt to rethrow an exception when no exception is currently distributed.
  • Unexpected exception excludes function using exception qualifiers (using unexpected)
+1
Oct 21 '08 at 15:49
source share



All Articles