Let say I have RAII class:
class Raii {
Raii() {};
~Raii() {
if (<something>) throw std::exception();
}
};
And if I have the function:
void foo() {
Raii raii;
if (something) {
throw std::exception();
}
}
This is bad because while cleaning for the first exception we can throw again and this will terminate the process.
My question is - What is a good pattern to use raii for code that the cleanup might throw?
For example is this good or bad - why?
class Raii {
Raii() {};
~Raii() {
try {
if (<something>) throw std::exception();
}
catch (...) {
if (!std::uncaught_exception())
throw;
}
}
};
Note that Raii object is always stack-allocated object - and this is not the general throw from destructor problem.
C++ will almost certainly have a function to obtain the current exception count as of C++1z (aka C++17 if they publish it on time!): std::uncaught_exceptions
(note the plural "s"). Also, destructors are declared as noexcept
by default (meaning that if you attempt to exit a destructor via an exception, std::terminate
is called).
So, first, mark your destructor as throwing (noexcept(false)
). Next, track the number of active exceptions in ctor, compare it to the value in dtor: if there are more uncaught exceptions in the dtor, you know that you are currently in the process of stack unwinding, and throwing again will result in a call to std::terminate
.
Now you decide exactly how exceptional you really are and how you wish to handle the situation: terminate the program, or just swallow the inner exception?
A poor imitation is to not throw if uncaught_exception
(singular) returns true, but that makes the exceptions not work when called from a different dtor's triggered by unrolling that is trying to catch and process your exception. This option is available in current C++ standards.