34

I've got C++ functions that I want to declare using extern "C" even though they are only called in C++ code. Yes, I know this is strange but it's something I would like to do for consistency since we have mixed C and C++ declarations. I just want to make sure that declaring a C++ function as extern "C" won't affect the behavior of throwing.

It would look something like this:

extern "C" void foo() {throw exception;}

int bar()
{
    try
    {
        foo();
    } catch (exception e) { return 1; }
}
5
  • Related question. Commented Apr 6, 2013 at 0:38
  • 1
    The answers assert that you're invoking undefined behaviour if an exception is thrown from C++ code into actual C code (which would not know what to do with an exception). I think that's correct, but are you asking about calling the extern "C" functions from C++ or from C? If you're calling them from C++ (and never from C), there's the inevitable question "why are the functions extern "C" if they're never called from another language?", but I think that simply calling C++ functions with extern "C" from C++ means there is no language boundary crossed and therefore no undefined behaviour. Commented Apr 6, 2013 at 0:49
  • Thanks to everyone who contributed to answering this. If I understand correctly, the ultimate answer to my question was this: extern "C" does not change the way an exception is handled. However, throwing an exception that is not caught and crosses language boundaries has undefined behavior. Commented Apr 9, 2013 at 18:05
  • q:"extern "C" does not change the way an exception is handled" -- I do not read the answers that way. Specifically /EHsc says otherwise. Commented Aug 1, 2014 at 19:48
  • 1
    @JonathanLeffler every compiler version of cpp is another language. If you have a msvc static library it will not work with GCC unless it was a C library using extern "C". Every compiler is allowed to mangle names how they feel, so you end up with undefined references when the reference actually exists. I think and don't see any reason why name mangling shouldn't be standardized; but this is a common reason for using extern "C" for C++ only. Example, I must create dll to use code from msvc in gcc as the code requires msvc specific stuff. Then I must use extern "C" to suppress name mangling. Commented Aug 31, 2021 at 6:21

4 Answers 4

19

"Can C++ functions marked as Extern “C” throw?"

Yes, in the sense that neither the language nor the compiler will prevent you from doing so.

No, in the sense that if you throw, it would be an undefined behaviour, as the C++ exception crosses language boundaries.

In practice: do not do it. Catch the exception and translate it into an error code, or a means the other language can understand.

So the bottomline is: do NOT throw exception from functions marked as extern "C".

Sign up to request clarification or add additional context in comments.

11 Comments

You can't say YES when its undefined behavior. When you invoke undefined behavior your code is basically broken.
@LokiAstari, the question was asked can they throw, and the answer is yes. If an extern "C" function was invoked directly from a function with c++ linkage, there is no undefined behavior. Same function invoked from C, undefined behavior. There isn't necessarily a language cross just because of linkage, but it is certainly a smell.
@LokiAstari, I must take exception with your statement, "You can't say YES when its undefined behaviour." "Undefined behavior" is immaterial to whether or it can or should happen. It only specifies that the result is undefined. It does not specify that it can never occur. Exceptions crossing boundaries happens all the time. C++->C; C++->Java; C++->Python. The difference is, most language translation library provide a facility to catch, translate, and rethrow exceptions into the target language.
Your first assumption is wrong: If an extern "C" function was invoked directly from a function with c++ linkage. If it throws its undefined behavior. The ABI for a C function does not contain the information needed to allow stack unrolling.
I have to agree with @LokiAstari. In my code, I have C++ calling a extern c function that throws an exception, and it is not being caught (even with catch(...)). Compiler is Intel compiler (icpc). All code is written in C++, there is no C. The linkage difference seems to be enough to break the stack unrolling.
|
9

For GCC the answer seems inconclusive.

The MSVC documentation, however is relatively clear on the subject:

  • /EHa and /EHs ... tells the compiler to assume that functions declared as extern "C" may throw an exception.
  • /EHsc ... tells the compiler to assume that functions declared as extern "C" never throw a C++ exception

So for Visual-C++ it depends on the compiler options whether you get defined behavior.

1 Comment

+1, but you missed the gcc answer in one of the linked comments: -fexceptions. From the gcc docs: "...you may need to enable this option when compiling C code that needs to interoperate properly with exception handlers written in C++".
2

it will compile but it is undefined behavior to throw from function marked as having C linkage. C doesn't have exceptions, therefore in general you should just return an error code and/or provide a function that returns the information about the last error.

#include <exception>
extern "C" void foo() {throw std::exception();}

compiles well

Comments

0

Here is answer for your question: http://yosefk.com/c++fqa/mixing.html#fqa-32.6

Basically you won't be able to catch it. (but why you won't just compile it and try? :))

3 Comments

"compile it and try" is never a good idea for languages with undefined behavior.
But it might lead you to make false assumptions about the behaviour of the code when in fact you shouldn't assume anything at all, because it's undefined and a compiler could do anything with it.
@PiotrJaszkowski: It may not destroy the universe but dragons will spew out your nose. Trying undefined behavior is pointless you don't learn anything as the test has no meaning.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.