7

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.

Ajay
  • 18,086
  • 12
  • 59
  • 105
gaurav bharadwaj
  • 1,669
  • 1
  • 12
  • 29
  • 7
    [Don't throw exceptions in destructors](http://stackoverflow.com/questions/130117/throwing-exceptions-out-of-a-destructor). – Some programmer dude Apr 18 '17 at 12:55
  • 2
    g++ says: "main.cpp:12:15: warning: throw will always call terminate() [-Wterminate]" "main.cpp:12:15: note: in C++11 destructors default to noexcept" – aschepler Apr 18 '17 at 13:02
  • 1
    The more relevant previous question is here: http://stackoverflow.com/a/16540757/1858225 – Kyle Strand Apr 18 '17 at 13:11

2 Answers2

15

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.

Community
  • 1
  • 1
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
4

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.

Marco A.
  • 43,032
  • 26
  • 132
  • 246