C++ : Catch a divide by zero error
这是一段简单的代码,其中除以零。 我想抓住它:
1 2 3 4 5 6 7 8 9 10 11 12 13 | #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的选项
是否有可能捕获到这样的异常(我理解的不是C ++异常,而是FPU异常)?
我知道我可以在分割之前检查除数,但是我假设,因为除零是罕见的(至少在我的应用程序中),尝试分割会更有效(并且如果 它发生)而不是每次除数前的除数。
我正在WindowsXP计算机上进行这些测试,但是想让它跨平台。
这不是一个例外。这是一个错误,它在硬件级别确定并返回给操作系统,操作系统然后以某种特定于操作系统的方式通知您的程序(例如,通过终止进程)。
我相信在这种情况下发生的事情不是例外,而是信号。如果是这种情况:操作系统会中断程序的主控制流并调用信号处理程序,而信号处理程序又会终止程序的运行。
这是与取消引用空指针时出现的相同类型的错误(然后您的程序因SIGSEGV信号崩溃,分段错误)。
你可以尝试使用
这是对MinGW 4.5,Windows 7的测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 | #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; } |
输出:
Signal 8 here!
在执行信号处理程序后,系统立即终止进程并显示错误消息。
使用此方法,您可以关闭所有资源或在除以零或空指针取消引用后记录错误...但不像异常那样即使在特殊情况下也不能控制程序的流程。有效的程序不应该这样做。捕获这些信号仅用于调试/诊断目的。
(有一些有用的信号在低级编程中非常有用,并且不会导致程序在处理程序之后被杀死,但这是一个很深的主题)。
除以零是一个逻辑错误,程序员的错误。你不应该尝试应对它,你应该调试并消除它。此外,捕获异常是非常昂贵的 - 比分数检查更多。
您可以使用结构化异常处理来捕获除以零的错误。如何实现取决于您的编译器。 MSVC提供了一个将结构化异常作为
没有
语言标准的捕捉方式
来自CPU的零除。
不要过早地"优化"掉一个
科。是你的申请
在这种情况下真的受CPU约束?我怀疑它,它不是真的
如果您破坏了代码,则进行优化
否则,我可以制作你的代码
甚至更快:
1 | int main(int argc, char *argv[]) { /* Fastest program ever! */ } |
除以零在C ++中不是例外,请参阅https://web.archive.org/web/20121227152410/http://www.jdl.co.uk/briefings/divByZeroInCpp.html
不知怎的,真正的解释仍然缺失。
Is it possible to catch such an exception (which I understand is not a C++ exception, but a FPU exception) ?
是的,您的
在Windows(使用Visual C ++)上,试试这个:
1 2 3 4 5 6 7 8 9 10 11 12 13 | BOOL SafeDiv(INT32 dividend, INT32 divisor, INT32 *pResult) { __try { *pResult = dividend / divisor; } __except(GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { return FALSE; } return TRUE; } |
MSDN:http://msdn.microsoft.com/en-us/library/ms681409(v = vs。85).aspx
为了避免无限"信号8在这里!" 消息,只需将'exit'添加到Kos好的代码中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #include <csignal> #include <iostream> #include <cstdlib> // exit using namespace std; void handler(int a) { cout <<"Signal" << a <<" here!" << endl; exit(1); } int main() { signal(SIGFPE, handler); int a = 1/0; } |
好吧,如果有关于此的异常处理,实际上需要一些组件来进行检查。因此,如果您自己检查,您不会丢失任何东西。并没有比简单的比较语句更快的速度(单个CPU指令"如果等于零则跳转"或类似的东西,不记得名称)
正如其他人所说,这不是一个例外,它只是生成一个NaN或Inf。
零分割只是实现这一目标的一种方式。 如果你做了很多数学,有很多方法,比如
如果您在进行计算之前可以检查有效参数,那么这样做,但有时这很难做到,因此您可能需要生成并处理异常。
在MSVC中,有一个包含函数
我很确定MinGW有类似的东西。
你可以在计算后测试它并抛出/捕获你自己的异常或其他什么。