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”