I wrote the following program:
// Example program
#include <iostream>
#include <string>
#include <exception>
struct A {
A() {
std::cout << "A ctor" << std::endl;
}
~A() {
std::cout << "A dtor" << std::endl;
try {
throw std::exception();
} catch (std::exception &e) {
std::cout << "Internal exception caught" << std::endl;
}
}
};
int main()
{
try {
A a;
throw std::exception();
} catch (std::exception &e) {
std::cout << "External exception caught" << std::endl;
}
}
The output I expected was:
A ctor
A dtor
Internal exception caught
External exception caught
And this is what I'm getting in GCC. But when I'm using Visual Studio (version 2013) the output I'm getting is:
A ctor
External exception caught
What's going on here?
MSVC2013 is wrong here and GCC is right. Unfortunately, I cannot find an appropriate reference from the standard now, but according to std::uncaught_exception:
For example, if stack unwinding causes a stack-allocated object to be destructed, the destructor for that object could run code that throws an exception as long as the exception is caught by some catch block before escaping the destructor.
For more details see also "Throwing during stack unwinding" section here.
Finally, as it is mentioned by @StoryTeller, this behaviour is not reproducible with newer MSVC versions.
The closest match in the standard I am able to find is the next (from the N3936 draft):
15.1 Throwing an exception [except.throw]
- If the exception handling mechanism, after completing the initialization of the exception object but before the activation of a handler for the exception, calls a function that exits via an exception, std::terminate is called.
So, formally, it is perfectly valid to call a function during stack unwinding process (including destructor) which might deal with exception, but if the exception inside such function is not caught by appropriate catch
block then std::terminate
must be called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With