Handling CPU exceptions in C++

2019-04-26 06:41发布

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

6条回答
神经病院院长
2楼-- · 2019-04-26 07:22

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.

查看更多
萌系小妹纸
3楼-- · 2019-04-26 07:27

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

查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-04-26 07:29

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.

查看更多
小情绪 Triste *
5楼-- · 2019-04-26 07:30

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.

查看更多
Lonely孤独者°
6楼-- · 2019-04-26 07:36

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

查看更多
相关推荐>>
7楼-- · 2019-04-26 07:41

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.

查看更多
登录 后发表回答