C++ : Catch a divide by zero error

2019-01-01 15:50发布

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).

Is it possible to catch such an exception (which I understand is not a C++ exception, but a FPU exception) ?

I'm aware that I could check for the divisor before dividing, 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.

9条回答
人气声优
2楼-- · 2019-01-01 16:25
  1. There's isn't a language-standard way of catching the divide-by-zero from the CPU.

  2. Don't prematurely "optimize" away a branch. Is your application really CPU-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! */ }
    
查看更多
倾城一夜雪
3楼-- · 2019-01-01 16:27

Well, if there was an exception handling about this, some component actually needed to do the 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)

查看更多
泪湿衣
4楼-- · 2019-01-01 16:28

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.

查看更多
姐姐魅力值爆表
5楼-- · 2019-01-01 16:32

It's not an exception. It's an error which is determined at hardware level 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 believe that 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).

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.


Here's the test on 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!

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).

查看更多
若你有天会懂
6楼-- · 2019-01-01 16:33

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) ?

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.

查看更多
登录 后发表回答