Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

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().

Code Block
bgColor#FFcccc

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 VOID ERR33-CPP. Destructors must not throw exceptions.

Code Block
bgColor#ccccff

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.