Throw exception from Destructor

Is it a good idea to throw an exception from a Destructor?
What happened if exception throws from a Destructor?
Good points:
1. No, It's not a good idea.
You can throw an exception in a destructor, but that exception must not leave the destructor; if a destructor exits by emitting an exception, all kinds of bad things are likely to happen because the basic rules of the standard library and the language itself will be violated. Don’t do it.

2. Destructor are by default noexcept.
(i.e. non-throwing, we do not expect exceptions from them, std::terminate is called in case of exception going out of destructor)

3. The Stack unwinding will happen after an exception and we may catch it outside. But don’t do it.
The C++ rule is that you must never throw an exception from a destructor that is being called during the “stack unwinding” process of another exception. For example, if someone says throw Foo(), the stack will be unwound so all the stack frames between the
 
 throw Foo()

and the
1
2
3
  }
  catch (Foo e)
  {

will get popped. This is called stack unwinding.
During stack unwinding, all the local objects in all those stack frames are destructed. If one of those destructors throws an exception (say it throws a Bar object), the C++ runtime system is in a no-win situation
> Is it a good idea to throw an exception from a Destructor?

No.
see: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Re-never-fail


> What happened if exception throws from a Destructor?

Among other things, it makes the standard library becomes unusable with such objects.
C.36 is a more specific guideline: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-dtor-fail

To be fair, there are a few libraries that use throwing destructors:
boost.log: https://github.com/boostorg/log/blob/master/include/boost/log/sources/record_ostream.hpp#L520
galera: https://github.com/codership/galera/blob/3.x/galerautils/src/gu_throw.hpp#L65
SOCI: https://github.com/SOCI/soci/blob/master/src/core/once-temp-type.cpp#L38

the way that works in all three cases is a temporary object is created at the start of an expression, each subsequent operator adds something to it, and at the semicolon, the temporary is destroyed, and its destructor performs the action. If the action fails, the destructor throws, so that the caller can handle the problem.
Last edited on
Topic archived. No new replies allowed.