einpoklum
einpoklum

Reputation: 132086

Add noexcept on otherwise-non-throwing inline functions calling C functions?

I've implemented C++ bindings for some C library. The library API calls can fail, but obviously can't throw anything; and my bindings are, for the purposes of this question, all inline.

Now, the compiler can figure out, for most of my inlined functions/methods, that an exception can't be thrown; for example, suppose I have:

bool foo() { 
    auto result = wrapped_lib_foo(); 
    return some_constexpr_nothrow_cond(result); 
}

should I mark such functions/methods with noexcept?

Notes:

Upvotes: 10

Views: 610

Answers (2)

doron
doron

Reputation: 28922

even if wrapped_lib_foo is a extern "C" function, the compiler has no way of knowing that somewhere down the stack wrapped_lib_foo never throws unless you tell it explicitly.

Then there is also that fact that marking the function noexcept explicitly informs your audience that the function does not throw.

So yes noexcept is a good idea.

Upvotes: 5

geza
geza

Reputation: 29970

I think this is good practice to add "noexcept", when you know a function doesn't throw. It is because a C function can throw, if it calls back into C++.

Whether this calling back to C++ and throw is allowed, seems to be compiler dependent. I've checked two compilers:

MSVC: has an option, /EHs, which:

The exception-handling model that catches C++ exceptions only and tells the compiler to assume that functions declared as extern "C" may throw an exception.

So, if this option is specified, then the compiler assumes that a C function can throw.

GCC: here's the documentation of -fexceptions:

Enable exception handling. Generates extra code needed to propagate exceptions. For some targets, this implies GCC generates 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 enables it by default for languages like C++ that normally require exception handling, and disables 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.

So, this implies that with -fexceptions, GCC compiles C code which can throw. Note, however: when calling a C function, the compiler doesn't know, whether the C code was compiled with -fexceptions, or not. So it has to assume, that it was. So, it seems that GCC must assume, that a C code can throw (the other possible way could be that -fexception would need to be specified for C++ code for telling the compiler that a called C code can throw, but doc of -fexceptions doesn't say anything like this).

Note: for GCC, throwing from a call stack, where a C function is involved, works even without the C code compiled with -fexceptions currently.

Upvotes: 4

Related Questions