3

According to C++ Standard (5/5) dividing by zero is undefined behavior. Now consider this code (lots of useless statements are there to prevent the compiler from optimizing code out):

int main() { char buffer[1] = {}; int len = strlen( buffer ); if( len / 0 ) { rand(); } } 

Visual C++ compiles the if-statement like this:

sub eax,edx cdq xor ecx,ecx idiv eax,ecx test eax,eax je wmain+2Ah (40102Ah) call rand 

Clearly the compiler sees that the code is to divide by zero - it uses xor x,x pattern to zero out ecx which then serves the second operand in integer division. This code will definitely trigger an "integer division by zero" error at runtime.

IMO such cases (when the compiler knows that the code will divide by zero at all times) are worth a compile-time error - the Standard doesn't prohibit that. That would help diagnose such cases at compile time instead of at runtime.

However I talked to several other developers and they seem to disagree - their objection is "what if the author wanted to divide by zero to... emm... test error handling?"

Intentionally dividing by zero without compiler awareness is not that hard - using __declspec(noinline) Visual C++ specific function decorator:

__declspec(noinline) void divide( int what, int byWhat ) { if( what/byWhat ) { rand(); } } void divideByZero() { divide( 0, 0 ); } 

which is much more readable and maintainable. One can use that function when he "needs to test error handling" and have a nice compile-time error in all other cases.

Am I missing something? Is it necessary to allow emission of code that the compiler knows divides by zero?

9
  • I assume your question only applies to fundamental types. Am I right? Commented Oct 17, 2011 at 7:02
  • @R. Martinho Fernandes: Yes, let's consider it limited to fundamental types. Commented Oct 17, 2011 at 7:12
  • The problem I see is that only a minority of errors would actually be caught at compile time the rest are really run time errors. I don't think there is another class of error that has this kind of duality. Which is a bit strange. Commented Oct 17, 2011 at 7:16
  • Also I would prefer to have a warning so it can be turned on/off as required for backwards comparability/testing etc Commented Oct 17, 2011 at 7:17
  • 1
    I was unconvinced a compiler was allowed to reject a well formed program just because of the existence of undefined behavior, but apparently it can. 1.3, under the definition of undefined behavior: "Permissible undefined behavior ranges from . . . to terminating a translation ... (with the issuance of a diagnostic message)." Its in a note rather than a proper rule, but it is good enough for me. However, I still would not want to see compilers be overly aggressive with this particular option. Commented Oct 17, 2011 at 7:50

5 Answers 5

4

There is probably code out there which has accidental division by zero in functions which are never called (e.g. because of some platform-specific macro expansion), and these would no longer compile with your compiler, making your compiler less useful.

Also, most division by zero errors that I've seen in real code are input-dependent, or at least are not really amenable to static analysis. Maybe it's not worth the effort of performing the check.

Sign up to request clarification or add additional context in comments.

4 Comments

Okay, but those functions are then broken, aren't they?
The last line seems most important to me. If 99% of the time the compiler can't know it is going to happen, how much are you really gaining going after the remaining cases?
I think the last paragraph is the answer. Compilers are slow enough as it is. Is it worth checking for one more error when it will almost never help the user? Nearly all divisions by zero are input dependent, so how much do we gain by checking for it at compile time?
@sharptooth: Maybe, maybe not. What if the reason they are never called is also the reason they contain the division by zero? Its rather like the warning about missing a return statement... if it only happens when i < 0, but i < 0 means some function I call is going to throw an exception I have no intention of catching, then the function is perfectly well formed and a hard error would be needlessly aggressive..
4

Dividing by 0 is undefined behavior because it might trigger, on certain platforms, a hardware exception. We could all wish for a better behaved hardware, but since nobody ever saw fit to have integers with -INF/+INF and NaN values, it's quite pointeless.

Now, because it's undefined behavior, interesting things may happen. I encourage you to read Chris Lattner's articles on undefined behavior and optimizations, I'll just give a quick example here:

int foo(char* buf, int i) { if (5 / i == 3) { return 1; } if (buf != buf + i) { return 2; } return 0; } 

Because i is used as a divisor, then it is not 0. Therefore, the second if is trivially true and can be optimized away.

In the face of such transformations, anyone hoping for a sane behavior of a division by 0... will be harshly disappointed.

5 Comments

I'm afraid I can't find the assert in this snippet.
Well, the second if statement is trivially true and can be optimized away. I'm guessing that's what he meant.
@sharptooth: I think he's referring to the "if (buf != buf + i)" test. Because i must not be zero (or we're in UB-land) that test is trivially true and it and everything following it can be legally replaced with "return 2".
@jalf: yes, sorry, I changed the example :x
Nice example. Even better is that the whole function can simply be replaced with return 2' since there is no integer value for i` where 5/i == 3.
1

In the case of integral types (int, short, long, etc.) I can't think of any uses for intentional divide by zero offhand.

However, for floating point types on IEEE-compliant hardware, explicit divide by zero is tremendously useful. You can use it to produce positive & negative infinity (+/- 1/0), and not a number (NaN, 0/0) values, which can be quite helpful.

In the case of sorting algorithms, you can use the infinities as initial values representing greater or less than all possible values.

For data analysis purposes, you can use NaNs to indicate missing or invalid data, which can then be handled gracefully. Matlab, for example, uses explicit NaN values to suppress missing data in plots, etc.

Although you can access these values through macros and std::numeric_limits (in C++), it is useful to be able to create them on your own (and allows you to avoid lots of "special case" code). It also allows implementors of the standard library to avoid resorting to hackery (such as manual assembly of the correct FP bit sequence) to provide these values.

Comments

0

If the compiler detects a division-by-0, there is absolutely nothing wrong with a compiler error. The developers you talked to are wrong - you could apply that logic to every single compile error. There is no point in ever dividing by 0.

1 Comment

...or you can just upvote it, and say downvotes without comments on passable zero score answers are for suckas... +1
0

Detecting divisions by zero at compile-time is the sort of thing that you'd want to have be a compiler warning. That's definitely a nice idea.

I don't keep no company with Microsoft Visual C++, but G++ 4.2.1 does do such checking. Try compiling:

#include <iostream> int main() { int x = 1; int y = x / 0; std::cout << y; return 0; } 

And it will tell you:

test.cpp: In function ‘int main()’: test.cpp:5: warning: division by zero in ‘x / 0’ 

But considering it an error is a slippery slope that the savvy know not to spend too much of their spare time climbing. Consider why G++ doesn't have anything to say when I write:

int main() { while (true) { } return 0; } 

Do you think it should compile that, or give an error? Should it always give a warning? If you think it must intervene on all such cases, I eagerly await your copy of the compiler you've written that only compiles programs that guarantee successful termination! :-)

1 Comment

MSVC does issue a warning. warning C4723: potential divide by 0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.