[Voted into the WP at the November, 2010 meeting.]
Proposed resolution (August, 2010): Change 14.6.2 [except.terminate] paragraph 1 as follows: In when the exception handling mechanism, after
completing evaluation of the expression to be thrown but
before the exception is caught (14.2 [except.throw]),
calls a function that exits via an when the exception handling mechanism cannot find a
handler for a thrown exception (14.4 [except.handle]),
or when the search for a handler (14.4 [except.handle]) encounters the outermost block of a function
with a noexcept-specification that does not allow the
exception (14.5 [except.spec]), or when the destruction of an object during stack
unwinding (15.2) terminates by throwing an exception,
or when initialization of a non-local variable with
static or thread storage duration (6.10.3.2 [basic.start.static] when destruction of an object with static or thread
storage duration exits when execution of a function registered with
std::atexit or
std::at_quick_exit exits when a throw-expression with no operand
attempts to rethrow an exception and no exception is being
handled (14.2 [except.throw]), or when std::unexpected throws an exception
which is not allowed by the previously violated
dynamic-exception-specification, and
std::bad_exception is not included in that
dynamic-exception-specification
(_N4606_.15.5.2 [except.unexpected]), or when the implementation's default unexpected
exception handler is called (_N4606_.D.6.1 [unexpected.handler]) when the function
std::nested_exception::rethrow_nested is called for
an object that has captured no exception (17.9.8 [except.nested]), or when execution of the initial function of a thread
exits via an exception (32.4.3.4 [thread.thread.constr]),
or when the destructor or the copy assignment operator
is invoked on a std::thread object that refers to a
joinable thread (32.4.3.5 [thread.thread.destr], 32.4.3.6 [thread.thread.assign]). —end note] Insert the following as a new paragraph following
14.2 [except.throw] paragraph 6: An exception is considered caught... If the exception handling mechanism, after
completing evaluation of the expression to be thrown but
before the exception is caught, calls a function that exits
via an exception, std::terminate is called (14.6.2 [except.terminate]). [Example: —end example] Change 14.3 [except.ctor] paragraph 3 as follows: Change 6.10.3.2 [basic.start.static] paragraph 6 as follows: Change 6.10.3.3 [basic.start.dynamic] paragraph 1 as follows: Change 17.5 [support.start.term] bullet 8.1 as
follows: First, objects with thread storage duration... If control leaves a registered function called by
exit because the function does not provide a
handler for a thrown exception, terminate() shall
be called (14.6.2 [except.terminate]).
the following some situations
exception handling must be abandoned for less subtle error
handling techniques:. [Note: These
situations are:
uncaught
exception, [Footnote: For example, if the object
being thrown is of a class with a copy constructor,
std::terminate() will be called if that copy constructor
exits with an exception during a throw. —end
footnote] or
, 6.10.3.3 [basic.start.dynamic])
terminates by throwing exits via an
exception, orusing via an
exception (6.10.3.3 [basic.start.dynamic]), orusing
via an exception (17.5 [support.start.term]),
or., or
struct C {
C() { }
C(const C&) { throw 0; }
};
int main() {
try {
throw C(); // calls std::terminate()
} catch(C) { }
}
The process of calling destructors for automatic objects
constructed on the path from a try block to a
throw-expression is called “stack
unwinding.”
[Note: If a
destructor called during stack unwinding exits with an
exception, std::terminate is called (14.6.2 [except.terminate]). [Note: So destructors
should generally catch exceptions and not let them propagate
out of the destructor. —end note]
[Note: If the initialization of a
non-local variable with static or thread storage duration
terminates by throwing exits via an
exception, std::terminate is called (see
14.6.2 [except.terminate]). —end note]
...
[Note: If the destruction of a
non-local an object with static or thread
storage duration terminates by throwing
exits via an exception, std::terminate
is called (see 14.6.2 [except.terminate]). —end note]
N3092 comment
GB 47 The list of reasons for which std::terminate is called
needs to be extended to cover several additional cases in
C++0x: when function
std::nested_exception::rethrow_nested is called for
an object that stores a null exception pointer. when execution of a function registered with
std::at_quick_exit exits using an exception. when the destructor or a copy constructor of class
std::thread is called for the object that is
joinable.