Partager via


Visual Studio and Arithmetic Overflow

Microsoft has made an important change between Visual Studio 2003 and Visual Studio 2005/2008:

By default, Visual Studio 2005/2008 projects have the “Check for arithmetic overflow/underflow” compilation switch turned off. In Visual Studio 2003, this switch defaulted to true.

What Does This Mean?

This means that if code attempts to multiply or add numbers that are very large (too large for the particular data type), the code will not throw an exception, but rather it will produce an unexpected result! This can lead to data corruption and potentially even infinite loops. (see “How We Discovered The Problem” below…)

Correcting the Problem

Every time you create a Visual Studio 2005 project:

  • Right-click on the project and bring up Properties.
  • Click on the Build tab.
  • Click on the Advanced… button. (You may need to scroll down to find it.)
  • Check the Check for arithmetic overflow/underflow checkbox.

Why Did Microsoft Do That?

Performance.

Checking for overflow requires a few extra programming cycles. Microsoft obviously traded safety for speed. (Although, this is a bit like saying “I can make a car faster if I don’t include brakes”.)

How I Discovered The Problem

I had written a little function that operated on a byte. I wanted to write a Unit Test Case to ensure that the function worked as expected for all possible byte values, so I wrote the following code:

for(byte b=0; b <= 255; b++) {     myFunction(b); }

However, there is a serious bug in the code above. Once b == 255, this function will try to increment b one more time which should cause an overflow. Rather than overflowing, b actually became 0 and it became an infinite loop!

I was shocked that I did not get an overflow exception, so then I tried…

byte b = byte.MaxValue; b++; Console.WriteLine(b);

And I received 0!

So I tried…

int i = int.MaxValue; i++; Console.WriteLine(i);

And I received a large negative number.

And finally, I tried…

int i = int.MaxValue; i *= 10; Console.WriteLine(i);

And I received -10!!!

At this point, I knew something was terribly wrong…

What If I Know That My Code Can’t Overflow?

In general, it’s better for us to be safe than sorry and always checked for overflow. HOWEVER, if you are 100% certain that you have a function that could never overflow, C# provides the unchecked { } block that allows you to mark a block of code to not require overflow checking.

I strongly advise against any developer actually using the unchecked statement unless you really, really, really know what you are doing!