Versions Compared

Key

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

...

When declaring an object with static or thread storage duration, and that object is not declared within a function block scope, the type's constructor must be declared noexcept(true) and must comply with ERR55-CPP. Honor exception specifications.

...

In this noncompliant example, the constructor for S may throw an exception that is not caught when globalS is constructed during program startup.

Code Block
bgColor#FFcccc
langcpp
struct S {
  S() noexcept(false);
};
 
static S globalS;

Compliant Solution

This compliant solution makes globalS into a local variable with static storage duration, allowing any exceptions thrown during object construction to be caught because the constructor for S will be executed the first time the function globalS() is called rather than at program startup. This solution does require the programmer to modify source code so that previous uses of globalS are replaced by a function call to globalS().

Code Block
bgColor#ccccff
langcpp
struct S {
  S() noexcept(false);
};
 
S &globalS() {
  try {
    static S s;
    return s;
  } catch (...) {
    // Handle error, perhaps by logging it and gracefully terminating the application.
  }
  // Unreachable.
}

Noncompliant Code Example

In this noncompliant example, the constructor of global may throw an exception during program startup (the std::string constructor accepting a const char * and a default allocator object is not marked noexcept(true) and consequently allows all exceptions). This exception is not caught by the function-try-block on main(), resulting in a call to std::terminate() and abnormal program termination.

Code Block
bgColor#FFcccc
langcpp
#include <string>
 
static const std::string global("...");

int main()
try {
  // ...
} catch(...) {
  // IMPORTANT: Will not catch exceptions thrown
  // from the constructor of global
}

Compliant Solution

Compliant code must prevent exceptions from escaping during program startup and termination. This compliant solution avoids defining a std::string at global namespace scope and instead uses a static const char *:

...

...