Take a look at this code which causes program to terminate without catching the exception.
#include <iostream>
#include <string>
#include <memory>
#include <stdexcept>
using namespace std;
struct test {
~test() noexcept(false) {
throw runtime_error("-my-cool-exception-");
}
};
int main()
{
try {
auto ptr = unique_ptr<test>(new test());
//test t; // this is ok, without unique_ptr<test> it works fine.
}
catch(exception& e) {
cout << "this is not called, the program is aborted";
cout << e.what() << endl;
}
return 0;
}
This question is different from stack overflow question: throwing exceptions out of destructor.
The difference is that only when I use unique_ptr<test>
the exception is not caught.
You can see the live code, edit and compile here http://cpp.sh/9sk5m
That's required by the standard. As per unique.ptr.single.dtor, 20.10.1.2.2.1:
Requires: The expression get_deleter()(get()) shall be well formed, shall have well-defined behavior, and shall not throw exceptions. [ Note: The use of default_delete requires T to be a complete type. — end note ]
(emphasis mine)
So really, it doesn't matter whether you destructor itself has noexcept(false)
or not. It's forbidden to throw in this case – final word.
This is the case in general the case std::
– except when specified otherwise. As per res.on.functions, 17.6.4.8.2.4:
In particular, the effects are undefined in the following cases: [...] if any replacement function or handler function or destructor operation exits via an exception, unless specifically allowed in the applicable Required behavior: paragraph.
(emphasis mine)
Note: In general, you can have throwing destructors with noexcept(false)
. However, this is very dangerous, as std::terminate
will be called if the stack was unwinding due to a thrown exception.
As per except.ctor, 15.2.1:
As control passes from the point where an exception is thrown to a handler, destructors are invoked by a process, specified in this section, called stack unwinding. If a destructor directly invoked by stack unwinding exits with an exception, std::terminate is called ([except.terminate]). [ Note: Consequently, destructors should generally catch exceptions and not let them propagate out of the destructor. — end note ]
(emphasis mine)
See it live on Coliru.
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