Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens when code that throws exceptions is linked against a library compiled with -fno-exceptions?

Specifically I'd like to know what, if any, guarantees are made by GCC about how code that throws exceptions behaves when linked against code compiled using -fno-exceptions.

The GNU libstdc++ manual says the following here.

Before detailing the library support for -fno-exceptions, first a passing note on the things lost when this flag is used: it will break exceptions trying to pass through code compiled with -fno-exceptions whether or not that code has any try or catch constructs. If you might have some code that throws, you shouldn't use -fno-exceptions. If you have some code that uses try or catch, you shouldn't use -fno-exceptions.

This sounds like a statement along the lines of, "Thou shalt not...." I.e. undefined behavior.

On the other hand, my impression from this SO question is that everything is kosher as long as the code compiled with -fno-exceptions doesn't throw, try, or catch (obviously a compile-time error) and exceptions never propagate through the functions from this library. And it makes sense: why should the library compiled with -fno-exceptions care if exceptions are thrown so long as they don't interact with its functions?

I did a little tinkering and found that if I compile a simple program using GCC 7.1.1 in which one source file is compiled with -fno-exceptions and the other throws and catches an exception, everything compiles, links, and runs fine. But that doesn't mean this behavior is guaranteed; it could still be undefined.

My motivation in all of this is that I have a situation in which I'm linking my own application code against a library built with -fno-exceptions and, depending on which function calls are made to said library, throwing an exception in my own code causes an immediate segfault even when that exception does not propagate through the library's functions. It smells like a bug in the library to me, but I thought maybe this was permitted when -fno-exceptions was passed during compilation.

GCC's actual reference on code-generation flags mentions -fexceptions relatively briefly and doesn't answer my question. Anyone know of another reference/have relevant experience?

Update: I rebuilt the library from source, this time with exception support turned on. The segfault persists! Time for a bug report.

like image 211
Sam Marinelli Avatar asked Aug 29 '17 09:08

Sam Marinelli


People also ask

What happens when an exception is thrown from the try with?

For try-with-resources, if an exception is thrown in a try block and in a try-with-resources statement, then the method returns the exception thrown in the try block. The exceptions thrown by try-with-resources are suppressed, i.e. we can say that try-with-resources block throws suppressed exceptions.

What happens to the program if there is an exception?

What happens if an exception is not caught? If an exception is not caught (with a catch block), the runtime system will abort the program (i.e. crash) and an exception message will print to the console. The message typically includes: name of exception type.

What happens when an exception is thrown Python?

If there's an exception, the code in the corresponding “except” block will run, and then the code in the “finally” block will run. If there are no exceptions, the code in the “else” block will run (if there's an “else” block), and then the code in the “finally” block will run.

What is exception handling what will happen if an exception is thrown for which no matching catch () block is defined?

If there is no catch block at the current scope matching the thrown exception, the current scope is exited, and all automatic (local nonstatic) objects defined in that scope are destroyed. The surrounding scope (which might be function scope) is checked for a matching handler.


1 Answers

As the linked question points out, GCC needs to allow -fno-exceptions and -fexceptions to co-exist, in order to link C and C++.

On a more theoretical level, the exception problem is closely related to the call graph of a program. This is a directed graph (caller/callee) but it can be cyclic, and there can be multiple edges between nodes. Now each function/node can be compiled with or without exceptions. We can define a safe program as a program in which no "with exceptions" node is reachable from a "without exceptions" node.

This may be unnecessarily strict - it might appear reasonable that a C++ bit of code within a try...catch(...) { } block should be callable from C code. But I don't know of a GCC guarantee for that. And consider what it means - the call graph is related to the call stack. The call stack generally forms a path from main() to the currently executing function. If the whole path is exception-aware, then exceptions are safe. But if there's one function which isn't aware of exceptions, it might have put the stack in a state in which exceptions cannot be handled safely, even if stack unwinding wouldn't unwind that far.

like image 178
MSalters Avatar answered Oct 08 '22 04:10

MSalters