https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55918
Sergey Barannikov <barannikov88 at gmail dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |barannikov88 at gmail dot com --- Comment #4 from Sergey Barannikov <barannikov88 at gmail dot com> --- This is the ABI problem. The search phase of the unwinding process cannot distinguish between a case when a true handler found and a case when the search process should stop, because it has reached a call site that must not pass the exception through. In both cases _URC_HANDLER_FOUND is returned by the personality routine, and the second phase of the unwinding process begins (the actual unwinding). There is another problem in LSDA format (in action table format to be precise). Consider the following example: void bad_guy() noexcept { try { Foo foo; throw 0; } catch (float) { // Don't catch int. } } void level1() { bad_guy(); throw "dead code"; } int main() { try { level1(); } catch (const char *) { } } When you compile and run it you get: Foo::Foo() terminate called after throwing an instance of 'int' Aborted (core dumped) It works as expected. But (the funny thing) if you change "catch (const char *)" in main to "catch (int)", you will get this: Foo::Foo() Foo::~Foo() terminate called without an active exception Aborted (core dumped) This is because there is currently no way to represent a "Terminate" action in the action table of LSDA. gcc represents it as a simply cleanup action, that means that the unwinder does not stop at a noexcept function and continues searching for a handler up the stack. In the original example there is no handler for the exception thrown, and the runtime terminates the program instantly (no stack unwinding done). When one changes "catch (const char *)" to "catch (int)", the unwinder finds this handler at the search phase and launches the second, unwinding, phase. The unwinding process then destroys the local object "foo", checks the exception type for matching "float", and falls into the code that calls std::terminate when the matching fails. Since there is no __cxa_begin_catch prior to std::terminate, we get the error message "terminate called without an active exception" instead of correct "terminate called after throwing an instance of 'int'".