在 C++ 中处理 CPU 异常

发布于 2024-10-14 01:43:19 字数 335 浏览 1 评论 0原文

是否有跨平台的方法来处理 CPU 异常,例如分段错误或除以零?可以说,我需要调用一些潜在不安全的函数(例如从插件文件),这可能会导致段错误,或在执行之前无法测试的一些其他问题。我知道,C 标准库有信号处理函数,但我不知道如何使用它们来处理问题以避免程序终止(我想,我不能只是跳转到有问题的函数执行之前的位置,或者我可以吗?)。 在 Windows 下我可以使用 SEH 异常处理程序,但在 Linux 或任何其他操作系统下我不能这样做。使用我自己的异常处理程序来处理这些问题怎么样?Windows/Linux 之间有多少不同?这可能吗(通过汇编器 - 比如说在 x86 平台上)?

我问这个问题主要是出于好奇,我还不想解决现有的问题。 谢谢

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

写下不归期 2024-10-21 01:43:19

我认为不存在真正的跨平台解决方案。

在 Windows 下,您可以使用 _set_se_translator 将 SEH 异常转换为 C++ 异常。

请参阅以下文章Linux 的 C++ 异常处理技巧,了解如何操作在Linux下做同样的事情

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

倾`听者〃 2024-10-21 01:43:19

不,没有标准方法。在 C++ 中,此类“CPU 异常”是未定义行为的表现,即 C++ 标准未指定有关其行为或之后发生的任何事情的任何内容。标准 C++ 中甚至不存在“段错误”的概念。取消引用 NULL 指针可能会导致计算机着火,显然此时已经没有什么可捕获的了。

C 也没有解决这个问题:SIGSEGV 不是标准的 C 信号;这是一个 POSIX 扩展。例如,Windows 没有 SIGSEGV。

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.

谁把谁当真 2024-10-21 01:43:19

信号处理程序可以将程序执行修复到某个点;到底允许什么内容记录在 signal(7) 手册页中。

有些实现将

  • 从 SIGSEGV 处理程序返回到错误指令(这允许您更改内存映射并返回),并

  • 转到 SIGFPE 故障之后的指令(因此您的信号处理程序需要查找指令并提供结果)

    转到 SIGFPE 故障之后的指令(因此您的信号处理程序需要查找该指令并提供结果)

请注意,这最多是实现定义的。该手册告诉您不要依赖任何这些。你已被警告过。 :)

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

爱情眠于流年 2024-10-21 01:43:19

libsigsegv 是一个跨平台库,用于处理分段错误和堆栈溢出。然而,在绝大多数情况下,当您检测到分段错误时,正确的做法是尽快终止执行,而不是尝试从中恢复。段错误通常表示错误或内存损坏,一旦内存损坏,几乎不可能从中恢复。

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.

等数载,海棠开 2024-10-21 01:43:19

问题是,如果插件段出现故障,您将无法保证主程序将处于什么状态。即使您可以捕获 SIGSEGV(我相信您可以),您也没有一个好的方法可以在您的应用程序中恢复。

您需要做的就是在分叉的进程中运行该插件,这样如果它崩溃了,您的主程序也不会被删除。例如,您可以使用管道在进程之间进行通信。

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.

孤寂小茶 2024-10-21 01:43:19

标准 C++ 中未涵盖这一点,但常见的桌面操作系统提供了执行此操作的工具。 Windows 具有结构化异常处理 (SEH),相关编译器扩展可用,并且 POSIX 提供信号处理。

通常,我会说你不应该捕获 CPU 异常 - 它们仅在你的程序出现错误时才会发生,此时,是时候破解调试器了,而不是继续。

即使在汇编程序中,您也不能使用相同的方法。这些功能由操作系统提供——当 CPU 引发异常时,它会由操作系统决定如何处理,而不是由用户模式决定。不仅如此,我想说 SEH 和信号处理很容易不同,足以保证在代码中使用它们时采用根本不同的方法,因此简单的 #ifdef 不会解决问题。

setjmplongjmp 只能用于用户模式代码发出的“信号”,而不是操作系统级别的信号。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文