C++:捕捉除以零错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4747934/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ : Catch a divide by zero error
提问by Jér?me
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;
}
But the application crashes anyway (even though I put the option -fexceptions
of MinGW).
但是应用程序无论如何都会崩溃(即使我选择-fexceptions
了MinGW)。
Is it possible to catch such an exception (which I understand is not a C++ exception, but a FPU exception) ?
是否有可能捕获这样的异常(我理解这不是 C++ 异常,而是 FPU 异常)?
I'm aware that I could check for the divisor beforedividing, 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.
我知道我可以在除法之前检查除数,但我假设,因为除以零是罕见的(至少在我的应用程序中),尝试除法会更有效(如果它发生)而不是在除法之前每次测试除数。
I'm doing these tests on a WindowsXP computer, but would like to make it cross platform.
我正在 WindowsXP 计算机上进行这些测试,但希望使其跨平台。
回答by Kos
It's not an exception. It's an errorwhich is determined at hardwarelevel 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 believethat 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.
我相信在这种情况下发生的不是例外而是信号。如果是这种情况:操作系统会中断程序的主控制流并调用信号处理程序,后者反过来终止程序的运行。
It's the same type of error which appears when you dereference a null pointer (then your program crashes by SIGSEGV signal, segmentation fault).
这与您取消引用空指针时出现的错误类型相同(然后您的程序因 SIGSEGV 信号、分段错误而崩溃)。
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.
您可以尝试使用<csignal>
header 中的函数来尝试为 SIGFPE 信号提供自定义处理程序(它用于浮点异常,但也可能是整数除以零引发的情况 - 我在这里真的不确定) . 但是,您应该注意信号处理依赖于操作系统,并且 MinGW 以某种方式“模拟”Windows 环境下的 POSIX 信号。
Here's the test on MinGW 4.5, Windows 7:
这是在 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;
}
Output:
输出:
Signal 8 here!
信号 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.
使用它,您可以在除以零或空指针取消引用后关闭任何资源或记录错误……但与异常不同的是,即使在特殊情况下,这也不是控制程序流程的方法。一个有效的程序不应该这样做。捕获这些信号仅用于调试/诊断目的。
(There are some useful signals which are very useful in general in low-level programming and don't cause your program to be killed right after the handler, but that's a deep topic).
(有一些有用的信号通常在低级编程中非常有用,并且不会导致您的程序在处理程序之后立即被终止,但这是一个深入的主题)。
回答by Puppy
Dividing by zero is a logical error, a bug by the programmer. You shouldn't try to cope with it, you should debug and eliminate it. In addition, catching exceptions is extremely expensive- way more than divisor checking will be.
除以零是一个逻辑错误,是程序员的错误。你不应该试图应付它,你应该调试并消除它。此外,捕获异常的代价是极其昂贵的——比除数检查要昂贵得多。
You can use Structured Exception Handling to catch the divide by zero error. How that's achieved depends on your compiler. MSVC offers a function to catch Structured Exceptions as catch(...)
and also provides a function to translate Structured Exceptions into regular exceptions, as well as offering __try
/__except
/__finally
. However I'm not familiar enough with MinGW to tell you how to do it in that compiler.
您可以使用结构化异常处理来捕获除以零错误。如何实现取决于您的编译器。MSVC提供了捕捉结构化异常的功能catch(...)
,并且还提供了一个函数来翻译结构化异常成规则的例外,以及产品__try
/ __except
/ __finally
。但是,我对 MinGW 不够熟悉,无法告诉您如何在该编译器中执行此操作。
回答by Greg D
There's isn't a language-standard way of catching the divide-by-zero from the CPU.
Don't prematurely "optimize" away a branch. Is your application reallyCPU-bound in this context? I doubt it, and it isn't really an optimization if you break your code. Otherwise, I could make your code even faster:
int main(int argc, char *argv[]) { /* Fastest program ever! */ }
没有一种语言标准的方法可以从 CPU 中捕获除以零。
不要过早地“优化”掉一个分支。在这种情况下,您的应用程序 真的受CPU 限制吗?我对此表示怀疑,如果您破坏代码,这并不是真正的优化。否则,我可以让你的代码更快:
int main(int argc, char *argv[]) { /* Fastest program ever! */ }
回答by ismail
Divide by zero is not an exception in C++, see https://web.archive.org/web/20121227152410/http://www.jdl.co.uk/briefings/divByZeroInCpp.html
除以零在 C++ 中也不例外,参见https://web.archive.org/web/20121227152410/http://www.jdl.co.uk/briefings/divByZeroInCpp.html
回答by Konrad Rudolph
Somehow the real explanation is still missing.
不知何故,仍然缺少真正的解释。
Is it possible to catch such an exception (which I understand is not a C++ exception, but a FPU exception) ?
是否有可能捕获这样的异常(我理解这不是 C++ 异常,而是 FPU 异常)?
Yes, your catch
block should work on some compilers. But the problem is that your exception is not an FPU exception. You are doing integer division. I don't know whether that's also a catchable error but it's not an FPU exception, which uses a feature of the IEEE representation of floating point numbers.
是的,您的catch
块应该适用于某些编译器。但问题是您的异常不是 FPU 异常。你在做整数除法。我不知道这是否也是一个可捕获的错误,但它不是 FPU 异常,它使用了浮点数的 IEEE 表示的功能。
回答by jalal sadeghi
On Windows (with Visual C++), try this:
在 Windows 上(使用 Visual C++),试试这个:
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
MSDN:http: //msdn.microsoft.com/en-us/library/ms681409(v= vs.85).aspx
回答by nibrot
To avoid infinite "Signal 8 here!" messages, just add 'exit' to Kos nice code:
为了避免无限的“信号8在这里!” 消息,只需将“退出”添加到 Kos 漂亮的代码中:
#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;
}
回答by Atmocreations
Well, if there was an exception handling about this, some component actually needed to dothe check. Therefore you don't lose anything if you check it yourself. And there's not much that's faster than a simple comparison statement (one single CPU instruction "jump if equal zero" or something like that, don't remember the name)
好吧,如果对此有异常处理,则某些组件实际上需要进行检查。因此,如果您自己检查,您不会丢失任何东西。没有什么比简单的比较语句更快的了(一个 CPU 指令“如果等于零则跳转”或类似的东西,不记得名字了)
回答by Mike Dunlavey
As others said, it's not an exception, it just generates a NaN or Inf.
正如其他人所说,这不是一个例外,它只是生成一个 NaN 或 Inf。
Zero-divide is only one way to do that. If you do much math, there are lotsof ways, likelog(not_positive_number)
, exp(big_number)
, etc.
零除法只是一种方法。如果你做太多的数学,也有很多的方式,比如log(not_positive_number)
,exp(big_number)
等等。
If you can check for valid arguments before doing the calculation, then do so, but sometimes that's hard to do, so you may need to generate and handle an exception.
如果您可以在进行计算之前检查有效参数,那么就这样做,但有时这很难做到,因此您可能需要生成和处理异常。
In MSVC there is a header file #include <float.h>
containing a function _finite(x)
that tells if a number is finite.
I'm pretty sure MinGW has something similar.
You can test that after a calculation and throw/catch your own exception or whatever.
在 MSVC 中,有一个头文件#include <float.h>
包含一个函数_finite(x)
,用于判断一个数是否有限。我很确定 MinGW 有类似的东西。您可以在计算后对其进行测试并抛出/捕获您自己的异常或其他任何内容。