October 15, 2006

Arithmetic overflows/underflows in C#; yes it is possible

I've been meaning to write about this for a few weeks; better late than never!

On day 3 of Building Connected Systems, Mr. Brown mentioned that it is possible to overflow numeric variables in C#. This surprised many other students in class (myself included) as developers assume 'managed code' takes care of this like it does with array bounds checking. From my understanding, VB.NET does not allow this scenario (I have not verified this, but trust Mr. Brown's assertion)!

When I started writing this entry, I was just going to do Int32, but after expanding to other integral and float types, I noticed differing behavior in how the .NET runtime handles this scenario. So, to try this out, I fired up a C# console app Visual Studio 2005 and here's what I found:

  • int.MaxValue + 1 == int.MinValue (it overflows and wraps around with no exception)
  • uint.MaxValue + 1 == 0 (it overflows to zero since it is unsigned; no exception thrown)
  • float.MaxValue + 1 == float.MaxValue (yes, the runtime handles the overflow, no exception is thrown, but it behaves differently tha int and uint)
  • double.MaxValue + 1 == double.MaxValue (same as float)
  • decimal.MaxValue + 1 throws a System.OverflowException

Keith's recommended turning on overflow checking for all C# projects and then using the 'unchecked' statement if you really need to squeeze performance out of your code. (My aside on this is that if you're really writing high perf code, perhaps managed code is not the optimal tool for the job?? One of my favorite Fergesonisms (circa 1998) is: "Use the right tool for the right job".
To turn on overflow/underflow checking in your C# project:
1. Right click on your project in the Solution Explorer and select Properties
2. On the Build tab, click the Advanced button
3. Make sure "Check for arithmetic overflow/underflow" is checked

An FxCop Rule or source control checkin policy would be two good tools to build around this! :)

jk

No comments: