No, it's not safe to throw any exceptions, including nested exceptions, from a destructor.
In C++, destructors are called in many situations, including during stack unwinding when an exception is thrown. If a destructor itself throws an exception during this process, it leads to undefined behavior, typically resulting in immediate termination of the program.
Here's an example of what not to do:
#include <stdexcept>
class Dangerous {
public:
~Dangerous() {
try {
throw std::runtime_error{
"Inner Exception"};
} catch(...) {
std::throw_with_nested(std::logic_error{
"Outer Exception"});
}
}
};
int main() {
try {
Dangerous d;
throw std::exception{};
} catch(const std::exception&) {
}
}
In this code, when the std::exception
is thrown in main()
, the Dangerous
object d
will be destroyed as part of stack unwinding. But its destructor throws another exception, leading to undefined behavior.
To avoid this, the C++ standard specifies that destructors should not throw exceptions. If a destructor needs to handle an exception, it should catch and handle it internally, not let it propagate.
For example:
#include <stdexcept>
#include <iostream>
class SaferButNotIdeal {
public:
~SaferButNotIdeal() noexcept {
try {
// Some operation that might throw
throw std::exception{};
} catch (...) {
// Handle the exception, but don't rethrow
std::cout << "Caught exception in "
"destructor\n";
}
}
};
int main() {
SaferButNotIdeal s;
}
Caught exception in destructor
Even better is to design your classes so that their destructors don't throw in the first place, by ensuring all operations in the destructor are non-throwing.
Answers to questions are automatically generated and may not have been reviewed.
Learn about nested exceptions in C++: from basic concepts to advanced handling techniques