2009-08-20

Code Gotchas: Borderline integer


Sometimes one finds a weird bug which “shouldn’t happen” but still does. And after more or less tedious debugging session the bug is found, and analyzing it shows it’s probably quite logical why the thing happened after all.

Even if it may be stressful to try find such nasty problems, in the end I’m usually fascinated by such weird minute details. Here is one such finding.

For this one I’ll present just the pure problem without a “solution” first, which I’ll add later. Feel free to add a comment and describe what you think — this one is actually really obvious.

Suppose you have a function “doStuff(x);” where x should be absolute value of the original. That is, the value passed to doStuff must be zero or positive. So you could have e.g. code like this:


int x;

// ... fill x with something ...

// and then find the absolute value...
x = abs(x);
// or alternatively just: if (x < 0) x = -x; // ... // and then do the work: doStuff(x);

Even that code can fail horribly. But why and how?

EDIT: Added clarification that also zero is ok.

Answer:

Absolute value of smallest integer doesn't fit in same sized integer but wraps back to being the same value. For example: if we assume size of int is 32 bits then if you assign -2147483648 (-0x80000000) to x, and execute "x = -x;", you'll still get the same value as result. Like suggested in the comments, the fix is to put the result to an unsigned integer: unsigned int x2; x2 = (unsigned int)abs(x); doStuff(x2);. Of course this assumes that the doStuff takes in also unsigned int. I deliberately left that out from the description... :-)

Note that with this whole thing we're of course assuming that two's-complement system is being used. But that probably includes any modern platform you're ever going to use so it is a safe assumption.

I have another gotcha which is kind of a nice continuation to this one, as it concerns use of unsigned integers. I'll write about that maybe next week.

CodeRSS feed for responses (closed) — Trackbacks disabled.