C++ C++;:捕捉被零除的错误
下面是一段简单的代码,其中出现了被零除的情况。我想抓住它:C++ C++;:捕捉被零除的错误,c++,performance,exception-handling,mingw,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.";
#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;
}
#包括
int main(int argc,char*argv[]){
整数=10;
整数除数=0;
试一试{
STD:CUT< P>除零在C++中也不是例外,参见除以0是一个逻辑错误,程序员的一个错误。你不应该尝试去处理它,你应该调试和消除它。此外,捕获异常是非常昂贵的。
您可以使用结构化异常处理来捕获被零除的错误。如何实现这一点取决于您的编译器。MSVC提供了一个函数来捕获结构化异常,如
catch(…)
,还提供了将结构化异常转换为常规异常的功能,并提供了\uuuu try
/\uuu,但最后
/\uu除外
。但是我对MinGW不够熟悉,无法告诉您如何在该编译器中执行此操作
没有一个
语言标准的捕捉方式
CPU中的数据被零除
不要过早地“优化”掉一个
你的申请是什么
在这种情况下,CPU真的受到限制吗?我对此表示怀疑,而且这并不是一个真正的问题
优化,如果你破坏了你的代码。
否则,我可以生成你的代码
更快:
int main(int argc, char *argv[]) { /* Fastest program ever! */ }
好吧,如果有一个异常处理,一些组件实际上需要做检查。因此,如果你自己检查它,你不会丢失任何东西。没有什么比一个简单的比较语句快(一条CPU指令“如果等于零则跳转”或类似的,不记得名称)这不是一个例外。这是一个错误,在硬件级别确定,并返回到操作系统,然后操作系统以特定于操作系统的方式通知您的程序(例如,通过终止进程)
我相信在这种情况下发生的不是异常而是信号。如果是这样的话:操作系统会中断程序的主控制流并调用信号处理程序,而信号处理程序反过来会终止程序的操作
这与取消引用空指针时出现的错误类型相同(然后程序因SIGSEGV信号、分段错误而崩溃)
您可以尝试使用
头中的函数来尝试为SIGFPE信号提供自定义处理程序(这是针对浮点异常的,但也可能是针对整数除以零而引发的情况-我在这里不确定)。但是,您应该注意,信号处理依赖于操作系统,并且在某种程度上是明的在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;
}
#包括
#包括
使用名称空间std;
无效处理程序(INTA){
不知何故,真正的解释仍然不清楚
是否可能捕获这样的异常(我理解它不是C++异常,而是FPU异常)?< /P>
是的,您的catch
块应该可以在某些编译器上运行。但问题是您的异常不是FPU异常。您正在执行整数除法。我不知道这是否也是一个可捕获的错误,但它不是FPU异常,它使用IEEE浮点数表示的功能。正如其他人所说,这不是一个例外,它只是生成一个NaN或Inf
零除法只是一种方法。如果你做了很多数学,有很多方法,比如
log(非正数)
,exp(大号)
,等等
如果在进行计算之前可以检查有效参数,那么就这样做,但有时这很难做到,因此可能需要生成并处理异常
在MSVC中有一个头文件#include
,其中包含一个函数\u finite(x)
,该函数告诉我们一个数字是否是有限的。
我很确定MinGW也有类似的东西。
您可以在计算后测试它,并抛出/捕获您自己的异常或其他任何异常。在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:为了避免无限的“这里有信号8!”消息,只需在Kos nice代码中添加“退出”:
#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;
}
#包括
#包括
#包括//退出
使用名称空间std;
无效处理程序(INTA){
CUT+1的建议是把墙上的洞固定起来,而不是试图在上面挂上一张图片。+ 1说,检查一个条件比捕获一个异常要便宜。检查对于一个非常微不足道的代码来说总是比一个例外更便宜——考虑科学计算,其中0个一般有一些有限但很小的概率。正在发生。我不同意“除以零==程序员错误”。想象一下你在一堆不可预测的输入数据(来自外部源、磁盘文件、网络等的数据)上运行一个复杂的算法这可能会导致除法为零,然后您意识到在每次使用/
运算符之前检查零非常麻烦。然后,像Windows SEH这样的东西就是一个很好的补救方法。如果(除数==0){std::cout(一个断言(除数!=0)
将更规范。不要忘记通过运行调试器进行开发!)这甚至不是FPU异常,而是CPU异常。FPU处理浮点数,但会得到NaN或无穷大,而不是崩溃。经验法则:始终(如果没有强调:始终!)在进行计算之前检查输入,可以避免此类问题。”我做了一个假设,因为被零除的情况很少见(至少在我的应用程序中是这样),所以效率会更高“,然后在运行探查器之前不要做这样的假设。突然做出假设是优化失败的一种方法。相信你的优化器和你CPU的分支预测。OP在问题中说了这一点。”有可能捕获这样的异常(我理解它不是C++异常,而是FPU异常)?“OP应该只做一个零C”