Petr
Petr

Reputation: 14505

why C++11 mark destructors as nothrow, and is it possible to override it?

So far I never had a single warning emitted by a C++ compilers but now VS 2015 compiler seems to suddenly start complaining about this.

It seems that C++11 implicitly mark every destructor as nothrow https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(C4297)&rd=true

Why is that? It may be a bad idea, but I would like to understand why? And if it's not inherently bad, is there a way to override it so that destructor is not a nothrow?

P.S. I know that exceptions may be evil, but sometimes they are usefull, especially when generating crash reports from users of my app.

Upvotes: 4

Views: 2871

Answers (4)

Oktalist
Oktalist

Reputation: 14714

The other answers have done a pretty good job of explaining why throwing in a destructor is a really bad idea. Sutter & Alexandrescu explain in C++ Coding Standards (2005) "Destructors, deallocation, and swap never fail", which is another way of saying they have no preconditions. Scott Meyers gives the canonical advice in Effective C++ (3rd Ed.) (2005) "Prevent exceptions from leaving destructors" and in Effective Modern C++ (2014) "Declare functions noexcept if they won't emit exceptions".

Engineering is often about trade-offs and compromises and difficult decisions. Sometimes you might need to throw in a destructor. You better have a damn good reason, and you're probably wrong. In such a case, you can declare the destructor noexcept(false) to override the default. Then you get the C++98 behaviour. And if you want to conditionally throw if the stack is not currently being unwound by another exception, you can use std::uncaught_exception. Handling errors that occur while handling errors is a rabbit hole you would be ill advised to venture down.

If your intent is to capture a snapshot of the state of the program at the moment that the exceptional state is detected, to phone home through Google Breakpad for example, then exceptions are not a good solution for that. The automated stack unwinding will discard useful information about the state of the program. You typically want to preserve the state of the stack in your crash report, which usually means calling std::terminate or std::abort.

Upvotes: 2

Petr Skocik
Petr Skocik

Reputation: 60097

Destructors are called when scopes are exited. When an exception is thrown, the stack is unwound which causes scopes to be exited and destructors to be called. When an exception is thrown while another is in progress, the process is unconditionally aborted with std::terminate. That is why throwing from destructors is a bad idea and why destructors are implicitly marked noexcept (==noexcept(true))*.

If you want to throw from a destructor anyway, you can explicitly mark it noexcept(false) to override the default.


*If you throw from a function marked noexcept, std::terminate is called immediately

Upvotes: 6

Logman
Logman

Reputation: 4189

Because if exception is thrown before application handle a current exception program will terminate.

Probably I will get many -1 for this but I will say it anyway. You can throw a exception inside destructor. You can also do many more things that most people will say it's "evil" and everything will be ok even more it will work better then without "evil" part. But you need to know exactly what are you doing.

Upvotes: 0

Jay Rajput
Jay Rajput

Reputation: 1898

Why is that? It may be a bad idea, but I would like to understand why? And if it's not inherently bad, is there a way to override it so that destructor is not a nothrow?

Throwing exceptions in a destructor is a bad idea. The reason being during an exception stack unwinding happens i.e. destructor for all the objects on the stack is called. Now, as the stack unwinding was happening as a part of the exception, the destructor throws an exception again. You can end up having multiple exceptions and then there is no un-ambiguous way of handling these multiple exceptions. E.g. if there are two exceptions and I have a catch block for one exception and not other, shall my process terminate or the exception caught and processed further?

Upvotes: 2

Related Questions