C++:捕获除零错误

Jér*_*ôme 27 c++ performance exception-handling mingw

这是一段简单的代码,其中除以零.我想抓住它:

#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;
}
Run Code Online (Sandbox Code Playgroud)

但是应用程序无论如何都会崩溃(即使我选择-fexceptionsMinGW).

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

我知道我可以分割之前检查除数,但我做了一个假设,因为除零是罕见的(至少在我的应用程序中),尝试分割会更有效(并且如果捕获错误则更有效)它发生)而不是每次除数前的除数.

我正在WindowsXP计算机上进行这些测试,但是想让它跨平台.

Kos*_*Kos 32

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

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

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

你可以尝试使用<csignal>头文件中的函数来尝试为SIGFPE信号提供一个自定义处理程序(它用于浮点异常,但也可能是因为整数除法也被提升为零 - 我真的不确定这里) .但是请注意,信号处理依赖于操作系统,MinGW以某种方式"模拟"Windows环境下的POSIX信号.


这是对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;
}
Run Code Online (Sandbox Code Playgroud)

输出:

信号8在这里!

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

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

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

  • Windows有一个很好的基于框架的异常处理工具(可能C++异常框架是在Windows工具上构建的).通过编译器开关可以将硬件异常转换为C++异常,但需要注意 - 过度热心的故障处理会使您进入未定义的状态.(注意,顺便说一下,我坚持将除零除以外的异常:操作系统和硬件将确认它是一个例外,它不是C++异常).编辑:oops,忽略了问题的MinGW部分.这可能会发生很大变化.无论如何,我会把我的胡扯留在这里. (3认同)
  • 它是特定于操作系统的.POSIX定义了这些; Windows不是POSIX兼容,但MinGW尽力弥补差距.对于Linux,你有[本手册页](http://unixhelp.ed.ac.uk/CGI/man-cgi?signal+7),"非致命"信号的常见例子是SIGSTOP,SIGTSTP(临时停止)和SIGCONT(继续). (2认同)

Pup*_*ppy 13

除以零是一个逻辑错误,程序员的错误.你不应该尝试应对它,你应该调试并消除它.此外,捕获异常是非常昂贵的 - 比分数检查更多.

您可以使用结构化异常处理来捕获除以零的错误.如何实现取决于您的编译器.MSVC提供了一个捕获结构化异常的函数,catch(...)并且还提供了将结构化异常转换为常规异常以及提供__try/ __except/的功能__finally.但是我对MinGW不太熟悉,告诉你如何在该编译器中完成它.

  • +1建议修复墙上的洞,而不是试图挂在它上面的图片. (4认同)
  • 呃,过度使用隐喻?我没有看到任何隐喻. (4认同)
  • 我不同意"除零==程序员错误".想象你在一堆不可预测的输入数据(来自外部源,磁盘文件,网络等的数据)上运行一个复杂的算法,它可能会导致除零,然后你会在每次使用`/`运算符之前检查零是非常麻烦的.然后,像Windows SEH这样的东西是一个很好的救援. (3认同)
  • +1表示检查条件比捕获异常便宜. (2认同)

Gre*_*g D 8

  1. 没有一种语言标准的方法可以从CPU中捕获零除零点.

  2. 不要过早"优化"一个分支.您的应用程序在此上下文中是否 真的受 CPU限制?我对此表示怀疑,如果你破坏你的代码,它并不是真正的优化.否则,我可以让你的代码更快:

    int main(int argc, char *argv[]) { /* Fastest program ever! */ }
    
    Run Code Online (Sandbox Code Playgroud)


ism*_*ail 6

除以零在C++中不是例外,请参阅https://web.archive.org/web/20121227152410/http://www.jdl.co.uk/briefings/divByZeroInCpp.html

  • OP在问题中表示."是否有可能捕获到这样的异常(我理解的不是C++异常,而是FPU异常)?" (3认同)