When an exception is thrown, terminate is called, even though there is an appropriate handler, if there is any C code between the exception and the handler. This is a serious problem because a lot of third party software uses a C ABI and callbacks. (Note that this works with Sun CC.) ---------- main.cc ------------ #include <ostream> #include <iostream> #include <stdexcept> extern "C" { extern void enrollCallback( void (*pf)() ) ; extern void doCallback() ; } void f() { throw std::runtime_error( "Just a test" ) ; } extern "C" void callback() { f() ; } int main() { enrollCallback( &callback ) ; try { doCallback() ; } catch ( std::exception const& error ) { std::cout << "Exception caught: " << error.what() << std::endl ; } catch ( ... ) { std::cout << "Unknown exception caught" << std::endl ; } return 0 ; } ------------ test.c ----------- static void (*pf)() ; void enrollCallback( void (*cb)() ) { pf = cb ; } void doCallback() { (*pf)() ; } -------------- end sources ----------- Desired behavior: Program outputs: > Exception caught: Just a test when run. (This is the behavior of Sun CC.) Actual behavior: terminate is called.
Subject: Re: New: exception not caught when passing through C code "jkanze at cheuvreux dot com" <gcc-bugzilla@gcc.gnu.org> writes: | When an exception is thrown, terminate is called, even though | there is an appropriate handler, if there is any C code between | the exception and the handler. This is a serious problem because | a lot of third party software uses a C ABI and callbacks. | (Note that this works with Sun CC.) This is documented somewhere in the docs, I think. If you mix C codes with C++ and exceptions are raised (through callbacks) and you need exceptions to smoothly travel across language boundaries, you need to compile the C code with -fexceptions. And yes, I too believe that Sun's approach is very sensible. Ah, I found the doc: ====================== @item -fexceptions @opindex fexceptions Enable exception handling. Generates extra code needed to propagate exceptions. For some targets, this implies GCC will generate frame unwind information for all functions, which can produce significant data size overhead, although it does not affect execution. If you do not specify this option, GCC will enable it by default for languages like C++ which normally require exception handling, and disable it for languages like C that do not normally require it. However, you may need to enable this option when compiling C code that needs to interoperate properly with exception handlers written in C++. You may also wish to disable this option if you are compiling older C++ programs that don't use exception handling. ====================== I thinks the PR can be closed. -- Gaby
*** This bug has been marked as a duplicate of 11813 ***
Subject: Re: exception not caught when passing through C code > This is documented somewhere in the docs, I think. If you mix C > codes with C++ and exceptions are raised (through callbacks) and > you need exceptions to smoothly travel across language > boundaries, you need to compile the C code with -fexceptions. The problem is that you don't always have the sources for the C code. Most of the time, it is in some third party library for which you only have the .h's and the .a (or .so). (And the third party library has likely been compiled with Sun's cc, not gcc.) I'll admit that I don't understand the problem, at least on Sparc. There is an ABI which defines what the C stack looks like; the C++ stack is, in fact, identical. Walking back the stack is trivial. The only thing you need the tables for is for finding destructor or handler code. So you won't find them in the C code which doesn't have the tables; that's no problem, because I'm pretty sure that the C code doesn't have any destructors, nor any exception handlers. Is there something linked with portability which precludes this approach. (I know that the stack walkback code is NOT portable. But I would have thought that this was true with or without the tables.) -- James Kanze GABI Software mailto: jkanze@cheuvreux.com Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 "This message, including any attachments may contain confidential and privileged material; it is intended only for the person to whom it is addressed. Its contents do not constitute a commitment by Credit Agricole Cheuvreux except where provided for in a written agreement. Credit Agricole Cheuvreux assumes no liability or responsibility for the consequences arising out of a delay and/or loss in transit of this message, or for corruption or other error(s) arising in its transmission and for any misuse or fraudulent use which may be made thereof. If you are not the intended recipient, please contact us and abstain from any disclosure, use or dissemination. To the extent that this message contains research information and/or recommendations, these are provided on the same basis as Credit Agricole Cheuvreux's published research and the recipient must have regard to all disclosures and disclaimers contained therein."
> I'll admit that I don't understand the problem, at least on > Sparc. There is an ABI which defines what the C stack looks > like; the C++ stack is, in fact, identical. Walking back the > stack is trivial. The only thing you need the tables for is for > finding destructor or handler code. This indeed may be true on SPARC. > So you won't find them in the C code which doesn't have the tables; that's no > problem, because I'm pretty sure that the C code doesn't have any > destructors, nor any exception handlers. Sure, but GCC nevertheless needs unwind info describing that there is no table and how to further unwind. > Is there something linked with portability which precludes this > approach. (I know that the stack walkback code is NOT portable. > But I would have thought that this was true with or without the > tables.) The exception propagation mechanism is generic and doesn't special-case SPARC at the moment.