58

The following code does not catch an exception, when I try to divide by 0. Do I need to throw an exception, or does the computer automatically throw one at runtime?

int i = 0;

cin >> i;  // what if someone enters zero?

try {
    i = 5/i;
}
catch (std::logic_error e) {

    cerr << e.what();
}
VLL
  • 9,634
  • 1
  • 29
  • 54
user33424
  • 625
  • 1
  • 5
  • 5

10 Answers10

80

You will need to check it yourself and throw an exception. Integer divide by zero is not an exception in standard C++. Neither is floating point divide/remainder by zero but at least that has specific rational values that may result (such as the various NaN/Inf values).

The exceptions listed in the [stdexcept.syn] section of ISO C++20 standard (the iteration used in this answer) are:

namespace std {
    class logic_error;
        class domain_error;
        class invalid_argument;
        class length_error;
        class out_of_range;
    class runtime_error;
        class range_error;
        class overflow_error;
        class underflow_error;
}

Now you could argue quite cogently that either overflow_error (the infinity generated by IEEE754 floating point could be considered overflow) or domain_error (it is, after all, a problem with the input value) would be ideal for indicating a divide by zero.

However, section [expr.mul] specifically states (for both integer and floating point division, and integer remainder):

If the second operand of / or % is zero, the behavior is undefined.

So, it could throw those (or any other) exceptions. It could also format your hard disk and laugh derisively :-)


If you wanted to implement such a beast, you could use something like intDivEx in the following program (using the overflow variant):

#include <iostream>
#include <stdexcept>

// Integer division/remainder, catching divide by zero.

inline int intDivEx (int numerator, int denominator) {
    if (denominator == 0)
        throw std::overflow_error("Divide by zero exception");
    return numerator / denominator;
}

inline int intModEx (int numerator, int denominator) {
    if (denominator == 0)
        throw std::overflow_error("Divide by zero exception");
    return numerator % denominator;
}

int main (void) {
    int i = 42;

    try {
        i = intDivEx (10, 0);
    } catch (std::overflow_error &e) {
        std::cout << e.what() << " -> ";
    }
    std::cout << i << std::endl;

    try {
        i = intDivEx (10, 2);
    } catch (std::overflow_error &e) {
        std::cout << e.what() << " -> ";
    }
    std::cout << i << std::endl;

    return 0;
}

This outputs:

Divide by zero exception -> 42
5

You can see it throws and catches the exception (leaving the return variable untouched) for the divide by zero case.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • Thanks, I was looking for the cases when system throws an exception, are these possible in c++? – user33424 May 25 '11 at 08:43
  • 1
    @user33424, yes it's possible, see my answer for example on `std::bad_alloc` which is thrown by `new` – iammilind May 25 '11 at 08:46
  • hmm so you don't have to choose carefully when you decide to use an exception class as they all take same parameter. – user33424 May 25 '11 at 09:09
  • @user But you should choose one that makes your intention clear about what went wrong. Throwing bad_alloc for e.g. invalid_argument is bad design. – RedX May 25 '11 at 09:40
  • 6
    As the domain of a function is the set of valid inputs for which the function is defined, wouldn't `domain_error` be more appropriate to throw here? – John H Mar 14 '14 at 18:21
  • I belive that `std::domain_error` is the correct one to throw here, since the division `a / b` is well defined except in the domain `b = 0`. – ruohola Jun 10 '19 at 09:34
  • @ruohola (and John H), I suspect I chose overflow (hard to tell since it was many years ago) because `domain_error` is a type of `logic_error`, which is usually concerned with stuff you should be able to detect at compile time. Not sure if divide-by-zero is covered in that since you may not *know* the denominator is zero until run-time. However, I've added that in as another possibility. – paxdiablo Jun 10 '19 at 12:13
  • +1 In Java, there is ArithmeticException that inherits from RuntimeException. So in my view, the best match would be std::runtime_error because there is no ArithmeticException equivalent in C++ – Hani Shams Jun 20 '21 at 08:09
  • @Hani, I concur. However, just keep in mind we are able to create *non-standard* exceptions that inherit from those standard ones. In other words, we could create a sub-class of `std::runtime_error` called `not_std::arithmetic_error`, and use that. The only restriction is that we couldn't/shouldn't place it into `std`. – paxdiablo Jun 20 '21 at 13:54
  • In my code C++17, x/0 return nan, no exception. – Kemin Zhou May 26 '22 at 15:55
  • @KeminZhou: I'm not sure what point you're making there. The answer *states* that no exceptions are thrown for divide by zero. – paxdiablo May 27 '22 at 00:47
  • I want to draw the attention of the special value nan instead of throwing an exception. – Kemin Zhou May 29 '22 at 01:57
30

Updated with comments from ExcessPhase

GCC (at least version 4.8) will let you emulate this behaviour:

#include <signal.h>
#include <memory>
#include <iostream>

int main() {
    std::shared_ptr<void(int)> handler(
        signal(SIGFPE, [](int signum) {throw std::logic_error("FPE"); }),
        [](__sighandler_t f) { signal(SIGFPE, f); });

    int i = 0;

    std::cin >> i;  // what if someone enters zero?

    try {
        i = 5/i;
    }
    catch (std::logic_error e) {
        std::cerr << e.what();
    }
}

This sets up a new signal handler which throws an exception, and a shared_ptr to the old signal handler, with a custom 'deletion' function that restores the old handler when it goes out of scope.

You need to compile with at least these options:

g++ -c Foo.cc -o Foo.o -fnon-call-exceptions -std=c++11

Visual C++ will also let you do something similar:

#include <eh.h>
#include <memory>

int main() {
    std::shared_ptr<void(unsigned, EXCEPTION_POINTERS*)> handler(
        _set_se_translator([](unsigned u, EXCEPTION_POINTERS* p) {
            switch(u) {
                case FLT_DIVIDE_BY_ZERO:
                case INT_DIVIDE_BY_ZERO:
                    throw std::logic_error("Divide by zero");
                    break;
                ...
                default:
                    throw std::logic_error("SEH exception");
            }
        }),
        [](_se_translator_function f) { _set_se_translator(f); });

    int i = 0;

    try {
        i = 5 / i;
    } catch(std::logic_error e) {
        std::cerr << e.what();
    }
}

And of course you can skip all the C++11-ishness of this and put them in a traditional RAII-managing struct.

Tom
  • 7,269
  • 1
  • 42
  • 69
  • Setting and restoring the signal handler should use RAII! Also you cannot assume, that the default signal handler was the one you temporarily replaced. –  Nov 03 '15 at 17:46
  • Thanks, @ExcessPhase, I've updated the answer to reflect this. – Tom Feb 23 '16 at 14:35
  • While compiling the visual c++ code in visual studio 2012, I am getting this error: "FLT_DIVIDE_BY_ZERO' : undeclared identifier". I have included "windows.h". Where am I going wrong ? – Nishant Jul 15 '16 at 04:10
  • I've fixed the GCC version. I don't have a VC++ install to hand to test it. – Tom May 25 '18 at 15:47
  • 1
    it is better in C++ include and call `std::signal` – kyb Jun 08 '18 at 14:51
  • 1
    And why do U use shared_ptr? As I understand to uninstall handlers with RAII. But if U don't share this pointer, it should be better use unique_ptr, or even custom RAII struct. – kyb Jun 08 '18 at 14:56
  • @kyb: I'm not really sure what std::signal adds here (or anywhere, for that matter). But you might well be right that unique_ptr would be a slightly better choice than shared_ptr. – Tom Jun 11 '18 at 13:20
  • 1
    Isn't FLT_DIVIDE_BY_ZERO and SIGFPE just for floating-point exceptions? – DodgyCodeException Dec 21 '18 at 15:04
  • @DodgyCodeException Isn't this question about catching divide-by-zero? – Tom Jan 04 '19 at 14:41
  • 2
    @Tom yes, it is about catching divide-by-zero, but what I'm trying to say is I thought FLT_DIVIDE_BY_ZERO and SIGFPE were just for floating-point exceptions and didn't think that _integer_ division by zero (the subject of this post) could be caught by either of these two signals. – DodgyCodeException Jan 05 '19 at 17:00
  • 2
    Ah, I see what you mean, but no, SIGFPE is for integer divide-by-zero too. Single Unix Specification defines SIGFPE as "Erroneous arithmetic operation." FLT_DIVIDE_BY_ZERO is indeed for floating-point-only and there is a corresponding INT_DIVIDE_BY_ZERO; I'll update the answer. – Tom Jan 08 '19 at 15:06
  • I've tried this code both in [online compiler](https://www.programiz.com/cpp-programming/online-compiler/) and docker with `gcc:10`. Tried std::signal as well. But in any case exception that is thrown from signal handler aborts application and is not catched. Only option that worked for me is using longjmp in signal handler. – Nickolay Andreychuk Jan 17 '23 at 19:21
11

As far as I know C++ specifications does not mention anything about divide by zero exeption. I believe you need to do it yourself...

Stroustrup says, in "The Design and Evolution of C++" (Addison Wesley, 1994), "low-level events, such as arithmetic overflows and divide by zero, are assumed to be handled by a dedicated lower-level mechanism rather than by exceptions. This enables C++ to match the behaviour of other languages when it comes to arithmetic. It also avoids the problems that occur on heavily pipelined architectures where events such as divide by zero are asynchronous."`

Thanatos
  • 42,585
  • 14
  • 91
  • 146
Mayank
  • 5,454
  • 9
  • 37
  • 60
2

You need to throw the exception manually using throw keyword.

Example:

#include <iostream>
using namespace std;

double division(int a, int b)
{
   if( b == 0 )
   {
      throw "Division by zero condition!";
   }
   return (a/b);
}

int main ()
{
   int x = 50;
   int y = 0;
   double z = 0;

   try {
     z = division(x, y);
     cout << z << endl;
   }catch (const char* msg) {
     cerr << msg << endl;
   }

   return 0;
}
yask
  • 3,918
  • 4
  • 20
  • 29
  • Or, alternatively, you can throw a more appropriate exception type, such as [std::invalid_argument](https://en.cppreference.com/w/cpp/error/invalid_argument) or [std::domain_error](https://en.cppreference.com/w/cpp/error/domain_error) – lionkor May 17 '23 at 14:09
1

setjmp + longjmp

https://stackoverflow.com/a/25601100/895245 mentioned the possibility or throwing a C++ exception from a signal handler, but Throwing an exception from within a signal handler mentions several caveats of that, so I would be very careful.

As another potentially dangerous possibility, you can also try to use the older C setjmp + longjmp mechanism as shown at: C handle signal SIGFPE and continue execution

main.cpp

#include <csetjmp>
#include <csignal>
#include <cstring>
#include <iostream>

jmp_buf fpe;

void handler(int signum) {
    longjmp(fpe, 1);
}

int main() {
    volatile int i, j;
    for(i = 0; i < 10; i++) {
        struct sigaction act;
        struct sigaction oldact;
        memset(&act, 0, sizeof(act));
        act.sa_handler = handler;
        act.sa_flags = SA_NODEFER | SA_NOMASK;
        sigaction(SIGFPE, &act, &oldact);
        if (0 == setjmp(fpe)) {
            std::cout << "before divide" << std::endl;
            j = i / 0;
            sigaction(SIGFPE, &oldact, &act);
        } else {
            std::cout << "after longjmp" << std::endl;
            sigaction(SIGFPE, &oldact, &act);
        }
    }
    return 0;
}

Compile and run:

g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out

Output:

i = 0
before divide
after longjmp
i = 1
before divide
after longjmp
i = 2
before divide
after longjmp

man longjmp says that you can longjmp from signal handlers, but with a few caveats:

POSIX.1-2008 Technical Corrigendum 2 adds longjmp() and siglongjmp() to the list of async-signal-safe functions. However, the standard recommends avoiding the use of these functions from signal handlers and goes on to point out that if these functions are called from a signal handler that interrupted a call to a non-async-signal-safe function (or some equivalent, such as the steps equivalent to exit(3) that occur upon a return from the initial call to main()), the behavior is undefined if the program subsequently makes a call to a non-async-signal-safe function. The only way of avoiding undefined behavior is to ensure one of the following:

  • After long jumping from the signal handler, the program does not call any non-async-signal-safe functions and does not return from the initial call to main().

  • Any signal whose handler performs a long jump must be blocked during every call to a non-async-signal-safe function and no non-async-signal-safe functions are called after returning from the initial call to main().

See also: Longjmp out of signal handler?

However Throwing an exception from within a signal handler mentions that this has further dangers with C++:

setjmp and longjmp aren't compatible with exceptions and RAII (ctors/dtors), though. :( You'll probably get resource leaks with this.

so you would have to be very very careful with that as well.

I guess the moral is that signal handlers are hard, and you should avoid them as much as possible unless you know exactly what you are doing.

Detect floating point zero division

It is also possible to detect floating point division by zero with a glibc call to:

#include <cfenv>

feenableexcept(FE_INVALID);

as shown at: What is the difference between quiet NaN and signaling NaN?

This makes it raises SIGFPE as well like the integer division by zero instead of just silently qnan and setting flags.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
1

You should check if i = 0 and not divide then.

(Optionally after checking it you can throw an exception and handle it later).

More info at: http://www.cprogramming.com/tutorial/exceptions.html

sifferman
  • 2,955
  • 2
  • 27
  • 37
Vadiklk
  • 3,696
  • 5
  • 28
  • 44
0

What about this one? Tested with Clang, GCC throws SIGILL.

#include <iostream>
#include <cassert>

int main()
{
    unsigned int x = 42;
    unsigned int y = x;
    y -= x;
    x /= y;
    
    std::cout << x << " != "<< *(&x) << std::endl;
    assert (*(&x) == x);
}
damkrat
  • 355
  • 3
  • 6
0

If you want to capture division by zero error involving integers (it's valid with float) without having to trigger it with a throw, you should use a signal handler like this:

void signalHandler( int signum ){
    //Division by 0 is c++ signal #8 (signum = 8).         
    cout << "Interrupt signal (" << signum << ") received.\n";
    exit(signum);
}

Then define this function as your signal handler before the code where division by zero may occur, like this:

int main(){
   ...
   signal(SIGFPE, signalHandler);
   ...
}

Note that SIGFPE is the signal for invalid arithmetic operation.

fredv
  • 1
  • 2
  • It's not generally safe to call something like `std::cout` in a signal handler. This is because std::cout may allocate, and may raise an exception, both of which are UB inside a signal handler. https://en.cppreference.com/w/cpp/utility/program/signal – lionkor May 17 '23 at 14:05
  • You're right. My sample code was just for illustration purposes that can be readily tested. It can be useful also during development stage. – fredv May 19 '23 at 05:59
-3

do i need to throw an exception or does the computer automatically throws one at runtime?

Either you need to throw the exception yourself and catch it. e.g.

try {
  //...
  throw int();
}
catch(int i) { }

Or catch the exception which is thrown by your code.

try {
    int *p = new int();
}
catch (std::bad_alloc e) {
    cerr << e.what();
}

In your case, I am not sure if is there any standard exception meant for divide by zero. If there is no such exception then you can use,

catch(...) {  // catch 'any' exception
}
iammilind
  • 68,093
  • 33
  • 169
  • 336
  • 3
    Division by zero is undefined behavior. – GManNickG May 25 '11 at 08:52
  • people, which do not know about this features existence (in Windows since more than 20 years and OSX) should not be answering here, nor voting nor calling themselves software engineers. –  Mar 01 '16 at 17:45
-5

You can just do assert(2 * i != i) which will throw an assert. You can write your own exception class if you need something fancier.

Kijewski
  • 25,517
  • 12
  • 101
  • 143
  • 3
    -1 I really dislike this solution. How is that easier than `assert(i != 0)`? I did not think through the border cases, but if it's not trivial to see that an assertion is stated correctly, then you should not put it. – Kijewski Jul 14 '12 at 23:09
  • 1
    In addition, `assert` is frequently deactivated in production code due to the presence of `NDEBUG` - `assert()` is typically a development-only method for catching problems. In any case, throwing an assertion is *not* throwing an exception. The former will abort your program rather than generate something you can catch. – paxdiablo Nov 03 '15 at 01:47