Multiple Exceptions
An exception handler can generate an arbitrary number of nested exceptions, but multiple exceptions cannot propagate simultaneously. Nesting is fine; concurrent propagation is not.
Why can nesting work but simultaneous propagation can't?
Nesting is sequential — the inner
catchruns to completion before the outer raise happens. Simultaneous propagation would mean two unwinds at once, and the runtime has no way to pick whichcatchhandles which without losing one. So the rule is: at most one exception propagating at a time.
Nested raise inside a handler
struct E {};
int cnt = 3;
void f( int i ) {
if ( i == 0 ) throw E();
try {
f( i - 1 );
} catch( E ) { // handler h
cnt -= 1;
if ( cnt > 0 ) f( 2 ); // raise inner E during outer handling
... throw; ...
}
}
int main() { f( 2 ); }Call trace: h catches inner throw → the body of h rethrows or throws a new E that propagates up through the next f frame → caught at the next outer h.
The simultaneous-propagation rules
- Cannot start a second exception without a handler to deal with the first (can’t drop).
- Cannot postpone the first because the second could remove its handlers while unwinding.
- Only destructor code can intervene during propagation — and even then, the destructor can only start a new propagation, not raise during one.
Detecting an in-flight exception
try {
C x; // C::~C is noexcept(false) and raises on deallocation
throw E(); // starts propagation
} catch( E ) { ... }When throw E() unwinds, x’s destructor wants to raise E too. Use uncaught_exceptions() inside the destructor to check if an exception is already being propagated, and skip the raise when it is.