I have written following program
#include <iostream>
#include <stdexcept>
class Myclass
{
public:
~Myclass()
{
//throw std::runtime_error("second (in destructor)");
throw 1;
}
};
void fun()
{
Myclass obj;
}
int main()
{
try
{
fun();
}
catch (const std::exception& e)
{
std::cout << e.what();
}
catch(...)
{
std::cout << " ... default Catch" << std::endl;
}
std::cout << "Normal" << std::endl;
return 0;
}
When I run above program in C++98
mode (cpp.sh) it prints
... default Catch
Normal
When I run it with C++14
mode, it does not print anything. Why is there a change in this behavior?
I do understand that whenever any exception occurred and any destructor
(within stack unwinding process) throws any exception, it terminates the application. But here only one time exception is thrown from try
block that is from destructor
.
There are two types of exceptions: a)Synchronous, b)Asynchronous (i.e., exceptions which are beyond the program's control, such as disc failure, keyboard interrupts etc.). C++ provides the following specialized keywords for this purpose: try: Represents a block of code that can throw an exception.
Use exceptions when the code that handles the error is separated from the code that detects the error by one or more intervening function calls. Consider whether to use error codes instead in performance-critical loops, when code that handles the error is tightly coupled to the code that detects it.
Exception handling is a mechanism that separates code that detects and handles exceptional circumstances from the rest of your program. Note that an exceptional circumstance is not necessarily an error. When a function detects an exceptional situation, you represent this with an object.
Exception specifications are a C++ language feature that indicate the programmer's intent about the exception types that can be propagated by a function. You can specify that a function may or may not exit by an exception by using an exception specification.
Since C++11, a destructor without an explicitly spelled out exception specification has the same exception specification as the default-generated one would have. In your case, the default-generated destructor would be noexcept
(most default-generated destructors are), so your destructor is considered noexcept
as well. Throwing from a noexcept
function automatically calls std::terminate
.
If you want the exception to be catchable, declare the destructor as throwing:
~Myclass() noexcept(false)
{
//throw std::runtime_error("second (in destructor)");
throw 1;
}
But before you do that, reconsider. It's a bad idea to have throwing destructors.
Throwing exceptions from destructors is always a bad idea since if there's already an exception in flight (e.g. destructor called during stack unwinding) std::terminate
will be called.
That said, C++11 added an implicit noexcept(true)
to destructors (except cases listed below) and that means, again, std::terminate
if throwing from a noexcept(true)
destructor.
§12.4/3
[class.dtor] [ Note: A declaration of a destructor that does not have a noexcept-specifier has the same exception specification as if had been implicitly declared (15.4). — end note ]
and §15.4/14
[except.spec] The exception specification for an implicitly-declared destructor, or a destructor without a noexcept-specifier, is potentially-throwing if and only if any of the destructors for any of its potentially constructed subojects is potentially throwing.
I strongly recommend restructuring your code in order not to throw in destructors.
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