Weird exception [duplicate]

3 weeks ago 20
ARTICLE AD BOX

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:

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.

Richard's user avatar

Richard

49.3k7 gold badges46 silver badges100 bronze badges

answered Oct 21, 2008 at 15:04

lefticus's user avatar

1 Comment

Upvote for referencing the official standard document.

2019-04-02T17:22:21.26Z+00:00

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.

answered Oct 22, 2008 at 12:19

Alex Che's user avatar

3 Comments

The selected answer mentioned terminate function which is the ultimate reason. However, I think this answer is closer to the correct answer. If one does not use try, it seems stack unwinding will no happen and that's why the destructor will not be called. My experiment seemed to suggest that the destructor is called when the correct error got caught, before the code block following catch is running.

2019-06-30T04:04:34.763Z+00:00

@SherAndrei If no matching handler is found, the function std::terminate() is called; whether or not the stack is unwound before this call to std::terminate() is implementation-defined. In you example there is no matching catch block: you throw runtime_error, but catch(int).

2024-10-02T12:24:39.41Z+00:00

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)

answered Oct 21, 2008 at 15:49

Loki Astari's user avatar

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.

answered Oct 21, 2008 at 14:58

James Curran's user avatar

6 Comments

No, this is wrong. The destructor is guaranteed to be called before the program leaves main. The cout destructor is guaranteed to be called afterwards.

2008-10-21T15:05:18.383Z+00:00

… correction: the destructor of a must be called before f is left!

2008-10-21T15:07:20.097Z+00:00

Also, the program never leaves main in the first example. It is aborted via terminate with via an "unexpected exception".

2008-10-21T15:08:24.4Z+00:00

@ejgottl: none of the conditions for terminating via terminate() nor unexpected() are met by this example. unexpected() would require a throw specification, and terminate() would need an exception in a dtor.

2008-10-21T15:16:04.963Z+00:00

@ejgotti: regardless, even if terminate() were called, as it shuts down, cout WILL STOP working, which was my point.

2008-10-21T15:17:08.923Z+00:00

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?

answered Oct 21, 2008 at 15:02

Klaim's user avatar

3 Comments

I created text file with first example (without try), opened "Visual Studio 2005 Command Prompt" and compiled file with cl /EHa my.cpp. Run result: This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information.

2008-10-21T15:16:59.89Z+00:00

I'm not familiar with the compilation parameters in command line, but i guess that it's similar to Release mode where if there is no try/catch the code will not get farther than the throw instruction (that's what happens when i try) and the application will just "crash" (that is the wanted behavior)

2008-10-21T15:44:27.277Z+00:00

Having looked at assembly listings, i believe optimizations are off by default. So it's closer to Debug. BTW, see comment by paercebal, s/he managed to reproduce with VS2003.

2008-10-21T16:11:14.227Z+00:00

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))

answered May 11, 2016 at 13:52

light_keeper's user avatar

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.

Read Entire Article