7

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

Jan Holecek
  • 2,131
  • 1
  • 16
  • 26
  • This may be of interest : http://stackoverflow.com/questions/4747934/c-catch-a-divide-by-zero-error – Jérôme Jan 25 '11 at 15:24
  • 1
    while in case of a segfault you cannot really do anything, I must admit the division by zero, overflow and underflow cases always struck me as odds and it would be great to be able to catch them. – Matthieu M. Jan 25 '11 at 16:23

6 Answers6

5

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.

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
  • Yes, such a solution would be applicable only to a few cases, where I can guarantee the program's environment wasn't otherwise corrupted. – Jan Holecek Jan 25 '11 at 15:42
  • @John Holecek How can you provide such a guarantee in any circumstances? – Mark B Jan 25 '11 at 16:09
  • For example to test if a pointer value points to a valid memory location - such a thing may be useful for a garbage collector of some sort. – Jan Holecek Jan 25 '11 at 16:45
  • @John Holecek: No, testing of a pointer is valid is actually likely to cause more bugs than it fixes. See http://blogs.msdn.com/b/oldnewthing/archive/2006/09/27/773741.aspx for a detailed discussion why. – Adam Rosenfield Jan 25 '11 at 18:41
  • Yeah, you are probably right. This approach would be buggy at best:-/ But this is in fact one of the reasons I've asked the question - to lean something new, and find out if it would work or not. – Jan Holecek Jan 26 '11 at 11:02
2

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 forked 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.

Mark B
  • 95,107
  • 10
  • 109
  • 188
  • The example with the plugin was just an idea where it might be used. Such a plugin would have to run either as a sub-process, as you suggested or it would have to follow a strict set of rules, as what it may, or may not do (but again, I wouldn't be able to enforce this). However in case where I just need to read/write to some memory, I should be able to recover in case of segfault. – Jan Holecek Jan 25 '11 at 15:36
2

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.

Puppy
  • 144,682
  • 38
  • 256
  • 465
2

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

Hasturkun
  • 35,395
  • 6
  • 71
  • 104
1

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.

MSalters
  • 173,980
  • 10
  • 155
  • 350
0

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. :)

Simon Richter
  • 28,572
  • 1
  • 42
  • 64