You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 7 Next »

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.

  • No labels