This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 116a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-12-19


1667. Function exiting via exception called by destructor during unwinding

Section: 14.2  [except.throw]     Status: NAD     Submitter: Ryou Ezoe     Date: 2013-04-25

According to 14.2 [except.throw] paragraph 7,

If the exception handling mechanism, after completing the initialization of the exception object but before the activation of a handler for the exception, calls a function that exits via an exception, std::terminate is called (14.6.2 [except.terminate]).

This could be read as indicating that the following example results in calling std::terminate:

  // function that exits via an exception
  void f() {
    // std::uncaught_exception() returns true here
    throw 0;
  }

  struct X {
    ~X() {
  // calls a function that exits via an exception
      try { f(); }
      catch( ... ) { }
    }
  };

  int main() {
    try {
      X x;
      throw 0; // calls X's destructor while exception is still uncaught.
    }
    catch( ... ) { }
  }

This seems undesirable, and current implementations do not call std::terminate. Presumably the intention is that the cited text only applies to functions that are called directly by the exception handling mechanism, which is not true of f() in this example, but this could be stated more clearly.

Rationale (September, 2013):

The intent of the wording in 14.2 [except.throw] paragraph 7 is to call std::terminate if an exception is propagated into the exception-handling mechanism; “If the exception handling mechanism... calls a function that exits via an exception” is thus intended to refer to functions that are directly called by the exception handling mechanism. In the given example, f() is not called by the exception handling mechanism, it is called by X::~X(). The exception handling mechanism calls X::~X(), but it does not exit via an exception, so std::terminate should not be called.