tags:

views:

284

answers:

2

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: http://stackoverflow.com/questions/2155442/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 : )

+10  A: 

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.

GMan
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
GMan: ANSI C Standard, 7.6.2 "Exceptions"
outmind
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
@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.
GMan
But how EXCEPTION_INT_DIVIDE_BY_ZERO do it in Windows? I'm think the underlying approach is not OS-specific.
outmind
@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.
GMan
§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
@GMan: Thanks. Reading it.
outmind
The standard quote was from me, but you're welcome.
Matthew Flaschen
Why have I been downvoted? :(
GMan
@Matthew: Thank you!
outmind
+1  A: 

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;
}
buttercup
Thanks. But does it help me catch integer division-by-zero exception?
outmind
Note: In float-point arithmetic and math world the result is "Infinity" not 0.
outmind
@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.
GMan
@GMan: It was a note to prevent novices use the code in their programs w/o consideration. I know about limits in calculus.
outmind
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
It does not help you trap an integer divide by zero, but it does help you not have a hard error in your program.<br>Example usage:<br>You have progress bar and with 0 items processed. The progress bar will cause a divide by zero error.<br><br>This helps trap the error before it goes to progress bar.
buttercup
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