9

It is known how to catch the float division-by-zero exception with the usage of

signal(SIGFPE, handler)

but it doesn't catch integer division-by-zero problem even if I setup control word with

_control87(0, _MCW_EM ); (MS VC 2010)

SubQuestion_1: How to catch integer division-by-zero in C program in Windows without usage of SEH EXCEPTION_INT_DIVIDE_BY_ZERO? (In Unix/Linux this can be done with usage of the standard signal/SIGFPE techinque)

EDIT: signal is ANSI C signal handling approach.
_control87 is the standard Windows function to set float control word.

Similar question: How to handle all errors, including internal C library errors, uniformly

NOTE (from ISO/IEC 9899:TC2 Annex H.2.2):

"The signed C integer types int, long int, long long int, and the corresponding unsigned types are compatible with LIA−1. ... C’s unsigned integer types are ‘‘modulo’’ in the LIA−1 sense in that overflows or out-of-bounds results silently wrap. An implementation that defines signed integer types as also being modulo need not detect integer overflow, in which case, only integer divide-by-zero need be detected."

?FINAL SOLUTION:

For Windows: it throws SEH exception. So it can be caught by usage of __try __except. As possible solution SEH translation could be used to handle SEH exception and translate them to call of needed function. It is not a "natural" way, but it seems that it's the only way.

For Unix: it could be caught with signal/SIGFPE solution. Or check wiki for FPE_INTDIV solution ( http://rosettacode.org/wiki/Detect_division_by_zero#C ).

As GMan was right about "undefined behaviour" I'm choosing his answer as correct.

Note: It is interesting to check VC\crt\src\winxfltr.c: _XcptActTab array : )

Community
  • 1
  • 1
outmind
  • 759
  • 1
  • 10
  • 30
  • 2
    Please explain your context better. Seeing signal, I guess your are on Unix? What is _control87? -1 for reposing a question that you seem to have asked some minutes ago. Please edit your first post, instead of creating a new one. – Jens Gustedt Jun 23 '10 at 21:13
  • 5
    This is not a feature of the C language, which doesn't have exceptions. It's platform-specific. Please provide which OS and compiler you're using. – David Thornley Jun 23 '10 at 21:13
  • 1
    Jens Gustedt: Concerning "-1" - these are two different questions. First was about why float division-by-zero exception didn't raise in the context of the called function. This one is about how to catch _integer_ division-by-zero. – outmind Jun 23 '10 at 21:28
  • possible duplicate of [Why "division by zero" wasn't caught even _control87 was called?](http://stackoverflow.com/questions/3105066/why-division-by-zero-wasnt-caught-even-control87-was-called) – Goz Jun 23 '10 at 21:33
  • Goz: no it's not. Read my comment above. – outmind Jun 23 '10 at 21:50

2 Answers2

21

Division by zero leads to undefined behavior, there is no C language construct that can do anything about it. Your best bet is to not divide by zero in the first place, by checking the denominator.

If you want to "catch" (note, C has no exceptions) this error, it will be dependent on your compiler and OS, which you haven't listed. By the way, _control87 has only to do with floating-point operations, and nothing to do with integer operations.

GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • I agree the best way is to make sure that you never divide by zero in the first place. The easiest way to do this is to do a global search through all your code and look for the '/' character for division and then take out the denominator and make it its own variable before division. Then add an if statement around the division to make sure the variable is not zero. – Brian T Hannan Jun 23 '10 at 21:34
  • GMan: ANSI C Standard, 7.6.2 "Exceptions" – outmind Jun 23 '10 at 21:42
  • GMan: It is possible to handle integer division-by-zero in Unix with SIGFPE and in Windows with SEH and EXCEPTION_INT_DIVIDE_BY_ZERO. But I'm trying to figure out how to do it in natural way w/ the min of platform specific functions. – outmind Jun 23 '10 at 21:49
  • 1
    @outmind: Oh, I see what you're saying, I equivocated. Well, sadly there is no standard way of catching division by zero, it's simply undefined behavior. And your other comment is exactly what we're saying: You *must* find an OS-specific way of doing it, the language C has no way. – GManNickG Jun 23 '10 at 21:52
  • But how EXCEPTION_INT_DIVIDE_BY_ZERO do it in Windows? I'm think the underlying approach is not OS-specific. – outmind Jun 23 '10 at 22:51
  • @outmind: What do you mean? Undefined behavior means the state of your program from that point forward does not follow any defined functionality. So *anything* could happen. Windows (probably using the CPU's divide-by-zero interrupt) decides to handle that situation by throwing an exception (Windows specific exception functionality). Typically, programs won't catch that OS-specific exception and that's when you get crashes. There's nothing standard about this though. – GManNickG Jun 23 '10 at 22:58
  • 2
    §6.5.5: Multiplicative opeators: "The result of the `/` operator is the quotient from the division of the first operand by the second; the result of the `%` operator is the remainder. In both operations, if the value of the second operand is zero, the behavior is undefined." – Matthew Flaschen Jun 23 '10 at 23:06
0

Check what you are dividing against...?

// if below = 0 then do not divide, just put answer as zero

if (below == 0) {
  result = 0;
} else {
  result = above/below;
}
R Samuel Klatchko
  • 74,869
  • 16
  • 134
  • 187
buttercup
  • 1,096
  • 16
  • 37
  • 3
    Thanks. But does it help me catch integer division-by-zero exception? – outmind Jun 23 '10 at 22:42
  • Note: In float-point arithmetic and math world the result is "Infinity" not 0. – outmind Jun 23 '10 at 22:49
  • @outmind: In math, it's still undefined. :) Floating point units tend to go to positive or negative infinity, depending in the signs of the operands, like you said. – GManNickG Jun 23 '10 at 22:54
  • @GMan: It was a note to prevent novices use the code in their programs w/o consideration. I know about limits in calculus. – outmind Jun 23 '10 at 23:00
  • hi, there is no other way to trap divide by zero other than putting 0. e.g., --> 0 / 0 = ?? The only thing you can do instead is to return 0 instead... :| – buttercup Jun 24 '10 at 03:31
  • It does not help you trap an integer divide by zero, but it does help you not have a hard error in your program.
    Example usage:
    You have progress bar and with 0 items processed. The progress bar will cause a divide by zero error.

    This helps trap the error before it goes to progress bar.
    – buttercup Jun 24 '10 at 03:35
  • To calculate the progress it is better to do itemsProcessed/itemsAmount than itemsAmount/itemsProcessed and 0/n (n>=1) will not cause divide by zero. And it is better to use the float point arithmetic in a progress bar, if you want any indication of an ongoing progress in a progress bar. – outmind Jun 24 '10 at 08:04
  • Returning 0 isn't always a good idea. This could hide the actual error which one may want to fix. – jigglypuff Feb 23 '17 at 06:31
  • @nobism: Using something like `((200*done)/total +1)/2` is generally a fine way to compute progress as a percentage for display, but it will blow up on the 0/0 case. In many cases, it really shouldn't matter whether one reports a degenerate task as 0% complete,100% complete, or N/A complete, but treating 0/0 as zero may be sufficient to handle that degenerate case without needing additional code elsewhere. – supercat Jul 04 '18 at 16:41