C++:捕捉除以零错误

2021-12-08 00:00:00 performance exception-handling mingw c++

这是一段简单的代码,其中发生了被零除.我正试图抓住它:

Here is a simple piece of code where a division by zero occurs. I'm trying to catch it :

#include <iostream>

int main(int argc, char *argv[]) {
    int Dividend = 10;
    int Divisor = 0;

    try {
        std::cout << Dividend / Divisor;
    } catch(...) {
        std::cout << "Error.";
    }
    return 0;
}

但是应用程序还是崩溃了(即使我设置了 MinGW 的选项 -fexceptions).

But the application crashes anyway (even though I put the option -fexceptions of MinGW).

是否有可能捕获这样的异常(我理解这不是 C++ 异常,而是 FPU 异常)?

Is it possible to catch such an exception (which I understand is not a C++ exception, but a FPU exception) ?

我知道我可以在除法之前检查除数,但我假设,因为除以零是罕见的(至少在我的应用程序中),它会更多尝试除法(并在发生错误时捕获错误)比在除法之前每次测试除数更有效.

I'm aware that I could check for the divisor before dividing, but I made the assumption that, because a division by zero is rare (at least in my app), it would be more efficient to try dividing (and catching the error if it occurs) than testing each time the divisor before dividing.

我正在 WindowsXP 计算机上进行这些测试,但希望使其跨平台.

I'm doing these tests on a WindowsXP computer, but would like to make it cross platform.

推荐答案

这也不例外.这是一个错误,它在硬件级别确定并返回给操作系统,然后操作系统以某种特定于操作系统的方式通知您的程序(例如,通过杀死过程).

It's not an exception. It's an error which is determined at hardware level and is returned back to the operating system, which then notifies your program in some OS-specific way about it (like, by killing the process).

我相信在这种情况下发生的不是异常而是信号.如果是这种情况:操作系统会中断您程序的主控制流并调用信号处理程序,从而终止程序的运行.

I believe that in such case what happens is not an exception but a signal. If it's the case: The operating system interrupts your program's main control flow and calls a signal handler, which - in turn - terminates the operation of your program.

这与取消引用空指针时出现的错误类型相同(然后您的程序因 SIGSEGV 信号而崩溃,分段错误).

It's the same type of error which appears when you dereference a null pointer (then your program crashes by SIGSEGV signal, segmentation fault).

您可以尝试使用 <csignal> 标头中的函数来尝试为 SIGFPE 信号提供自定义处理程序(它用于浮点异常,但也可能是这种情况整数除以零 - 我在这里真的不确定).但是,您应该注意信号处理依赖于操作系统,并且 MinGW 以某种方式模拟"了 Windows 环境下的 POSIX 信号.

You could try to use the functions from <csignal> header to try to provide a custom handler for the SIGFPE signal (it's for floating point exceptions, but it might be the case that it's also raised for integer division by zero - I'm really unsure here). You should however note that the signal handling is OS-dependent and MinGW somehow "emulates" the POSIX signals under Windows environment.

这是在 MinGW 4.5、Windows 7 上的测试:

Here's the test on MinGW 4.5, Windows 7:

#include <csignal>
#include <iostream>

using namespace std;

void handler(int a) {
    cout << "Signal " << a << " here!" << endl;
}

int main() {
    signal(SIGFPE, handler);
    int a = 1/0;
}

输出:

信号 8 在这里!

在执行信号处理程序后,系统立即终止进程并显示错误消息.

And right after executing the signal handler, the system kills the process and displays an error message.

使用此功能,您可以在除以零或空指针取消引用后关闭任何资源或记录错误...但与异常不同,即使在特殊情况下,也不能控制程序流程. 一个有效的程序不应该这样做.捕获这些信号仅用于调试/诊断目的.

Using this, you can close any resources or log an error after a division by zero or a null pointer dereference... but unlike exceptions that's NOT a way to control your program's flow even in exceptional cases. A valid program shouldn't do that. Catching those signals is only useful for debugging/diagnosing purposes.

(有一些有用的信号通常在低级编程中非常有用,并且不会导致您的程序在处理程序之后立即被杀死,但这是一个很深的话题).

相关文章