is there a cross-platform way to handle the CPU exceptions like segmentation faults, or division by zero? Lets say, I need to call some potentially unsafe functions (for example from a plug-in file), that can cause a segfault, or some other problems that I cannot test before I execute it. I know, that the C standard library has signal handling functions, but I don't know how to use them to handle the problem to avoid the program termination (I guess, I can't just jump to the location before the problematic functions execution, or can I?).
Under windows I could use the SEH exception handlers, but I can't do that under Linux, or any other OS. What about using my own exception handler to handle these problems, how much is that different between Windows/Linux? Would that be even possible (via assembler - lets say just on the x86 platform)?
I'm asking mostly out of curiosity, I'm not trying to solve an existing problem (yet).
Thanks
libsigsegv is a cross-platform library for handling segmentation faults and stack overflows. However, in the vast majority of cases, when you detect a segmentation fault, the right thing to do is to terminate execution as fast as possible instead of trying to recover from it. A segfault is usually indicative of a bug or corrupted memory, and once you have corrupted memory, it's virtually impossible to recover from that.
The problem is that if the plugin seg faults, you can't guarantee what state your main program will be in anymore. Even if you could catch SIGSEGV (which I believe you can) you wouldn't have a good way to recover in your application.
What you would have to do is run the plugin in a fork
ed process so that if it crashes your main program isn't taken down too. You could communicate between the processes with a pipe for example.
This is not covered in Standard C++, however common desktop OSes provide facilities to do this. Windows has Structured Exception Handling (SEH) for which relevant compiler extensions are available, and POSIX provides signal handling.
Typically, I would say that you shouldn't catch CPU exceptions- they only occur if your program is bugged and at that point, it's time to crack out a debugger, not continue.
You cannot use the same approach- even in assembler. These facilities are provided by the OS- when the CPU raises an exception, it goes to the OS to decide what to do about it, not user-mode. Not just that, but I would say that SEH and signal handling are easily different enough to warrant fundamentally different approaches when using them in code, so a simple #ifdef
won't cut it.
setjmp
and longjmp
can only work for "signals" raised by user-mode code, not OS-level.
I don't think a true cross platform solution exists.
under windows you can use _set_se_translator
to translate SEH exceptions to C++ exceptions.
See the following article C++ exception-handling tricks for Linux on how to do the same under Linux
No, there's no standard way. In C++, such "CPU exceptions" are manifestations of Undefined Behavior, i.e. the C++ standard doesn't specify anything about their behavior, or of anything that happens afterwards. Even the notion of a "segfault" doesn't exist in standard C++. Dereferencing a NULL pointer could set your computer on fire, and obviously there's little left to catch at that point.
C didn't solve this either: SIGSEGV isn't a standard C signal; it's a POSIX extension. Windows doesn't have SIGSEGV, for instance.
Signal handlers can fix up program execution to some point; what exactly is allowed is documented in the signal(7) manual page.
There are implementations that will
return to the faulting instruction from SIGSEGV handlers (this allows you to change the memory map and return), and
go to the instruction following the fault for SIGFPE (so your signal handler needs to look up the instruction and provide a result)
Note that this is implementation-defined at best. The manual tells you not to rely on any of this. You have been warned. :)