Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

  • Not a dupe of Should I use noexcept for simple functions that obviously cannot throw?, as in that case the compiler doesn't know whether the function can throw or not; for C functions - it does know.
  • The more general question When should I really use noexcept? has potentially conflicting answers, plus, the accepted answer is from 5 years ago and says "it's too early to say".
like image 831
einpoklum Avatar asked Nov 13 '17 10:11

einpoklum


People also ask

What happens when Noexcept function throws?

If you throw, your program terminates What happens if you throw from a noexcept function? Your program terminates, and may or may not unwind the stack. Terminating program isn't the nicest way to report an error to your user. You would be surprised that most of C++ code might throw.

Should I use Noexcept?

In general, you should use noexcept when you think it will actually be useful to do so. Some code will take different paths if is_nothrow_constructible is true for that type. If you're using code that will do that, then feel free to noexcept appropriate constructors.

What does Noexcept mean in C++?

noexcept (C++) C++11: Specifies whether a function might throw exceptions.

Is Noexcept faster?

That noexcept keyword is tricky, but just know that if you use it, your coding world will spin faster. The noexcept keyword is a recent addition, so when should you use it? Here's what the guideline says: If your function may not throw, declare it noexcept.


2 Answers

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.

like image 153
geza Avatar answered Oct 08 '22 22:10

geza


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.

like image 25
doron Avatar answered Oct 08 '22 22:10

doron