Not all exceptions can be caught. Quoting from [except.handle], p13 of N3000, the current Working Draft of the C++ standard:
Exceptions thrown in destructors of objects with static storage duration or in constructors of namespace-scope objects with static storage duration are not caught by a function-try-block on
main()
. Exceptions thrown in destructors of objects with thread storage duration or in constructors of namespace-scope objects with thread storage duration are not caught by a function-try-block on the initial function of the thread.
Non-Compliant Code Example
In the following non-compliant example, the constructor of global
may throw an exception during program startup. This exception is not caught by the function-try-block on main()
, resulting in a call to std::terminate()
. Similarly, the destructor of the local_static
object defined in function f(()
may throw an exception during program termination. This exception is also not caught by the function-try-block on main()
, again resulting in a call to std::terminate()
.
static const std::string global("..."); void f() { static const struct LocalClass { // ... ~LocalClass() { if (error_detected) throw std::runtime_error("..."); } } local_static; } int main() try { f(); // other executable statements } catch(...) { // handle exceptions thrown during the call to // f() and any other statements in the try block // above // IMPORTANT: will not catch exceptions thrown // from the constructor of global or those from // the destructor of local_static defined in f() // and invoked during program termination }
Compliant Solution
Compliant code must prevent exceptions from escaping during program startup and termination. A solution is to avoid defining at namespace scope objects whose constructors may throw, in addition to preventing exceptions from being thrown from destructors as outlined in ERR33-CPP. Destructors must not throw exceptions.
static const char global[] = "..."; void f() { static const struct LocalClass { // ... ~LocalClass() throw() { if (error_detected) { try { std::clog << "Runtime error: ...\n"; } catch(...) { // attempt to log error by other means } } } local_static; } int main() try { f(); } catch(...) { // handle exceptions thrown during the call to // f() and any other statements in the try block // above }
References
[[Sutter 00]] Sutter, Herb. Exceptional C++: 47 Engineering Puzzles, Programming Problems, and Solutions.