1
class D
{
public:
    ~D() { throw std::exception(); }
};
int main()
{
    try
    {
        try
        {
            D d;
        }
        catch (...)
        {
            cout << "1";
        }
    }
    catch (std::exception& e)
    {
        cout << "2";
    }
}

My understating is that this should be caught in 2. But its not caught, and instead program is terminated.

henryyao
  • 1,758
  • 6
  • 23
  • 37

1 Answers1

7

In C++11, destructors are implicitly noexcept, so std::terminate is called automatically if the destructor throws an exception that isn't caught within the destructor itself.

Even before that, destructors that throw an uncaught exception during stack unwinding cause std::terminate to be invoked, so what you're doing won't work if the destructor is invoked by some other exception bubbling up the stack.

If that's not a concern, you can explicitly declare your destructor to be ~D() noexcept(false) (which would allow exceptions to bubble out of the destructor if the destructor wasn't triggered by some other exception causing stack unwinding).

Note that even though it's technically legal, it's generally considered a bad idea to throw uncaught exceptions in a destructor, since it makes your class largely unusable in any context where a handleable exception might be thrown. You can read more at c++ exception in destructor (which isn't a strict duplicate, but covers your scenario completely).

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • 3
    Note that the destructor of `D` is not called during stack unwinding in the OP's example. – Brian Bi Aug 12 '19 at 16:12
  • @Brian why its not called? – henryyao Aug 12 '19 at 16:16
  • 1
    @henryyao The destructor is called but stack unwinding only starts after the destructor throws. At that point, there are no more objects to destroy. – Brian Bi Aug 12 '19 at 16:17
  • @Brian Isn't stack unwinding process calls destructors? – henryyao Aug 12 '19 at 16:22
  • @henryyao The destructor of `d` is only called once. Since it is called at the end of the try block, it does not get called a second time during stack unwinding. When stack unwinding begins, there are no objects left to destroy. – Brian Bi Aug 12 '19 at 16:23
  • 1
    @henryyao -- "stack unwinding" refers to the cleanup that's done when an exception has been thrown and is caught by a `catch` clause higher up. It's not about ordinary cleanup, which invokes destructors at the end of a block. The issue is what should happen when an exception is being processed and during that processing another exception is thrown. – Pete Becker Aug 12 '19 at 16:23
  • @Brian: Thanks, I've edited to correct/clarify that point. It's still a terrible idea to design a class to throw exceptions in the destructor, but it's not fundamentally broken in this very limited case. – ShadowRanger Aug 12 '19 at 16:59