C# Overflow not Working? How to enable Overflow Checking? - c#

I was working around with C# and noticed that when I had a very large integer and attempted to make it larger. Rather that throwing some type of overflow error, it simply set the number to the lowest possible value (-2,147,483,648) I believe.
I was wondering if there was a way to enable the overflow checking in Visual Studio?

You can use the following steps to enable Arithmetic Overflow/Underflow checking in Visual Studio :
Right click on your project in the Solution Explorer and select Properties.
On the Build tab, click the Advanced button. (It's towards the bottom)
Check the "Check for arithmetic overflow / underflow" check-box.
This will throw a System.OverflowException when the overflow occurs rather than it's usual operation of changing the value to a minimum value.
Without Arithmetic Overflow/Underflow enabled:
int test = int.MaxValue;
test++;
//Test should now be equal to -2,147,483,648 (int.MinValue)
With Arithmetic Overflow/Underflow enabled:
int test = int.MaxValue;
test++;
//System.OverflowException thrown
Using a checked block:
checked
{
int test = int.MaxValue;
test++;
//System.OverflowException thrown
}
The documentation for checked is available here. (Thanks to Sasha for reminding me about it.)

Related

How to enforce never divide two `int` [duplicate]

I am working on a calculation module using C#, and I bumped on this :
double v = 4 / 100;
I know this is a wrong initialization that returns v = 0.0 instead of v = 0.04
The c# rules says I must ensure at least one of the member is a double, like this :
double v = (double) 4 / 100;
double v = 4.0 / 100;
However, I have many many initializations of that kind that involves integer variables operations, and I feel lazy to browse my code line by line to detect such mistakes.
Instead, is it possible to get warned by the compiler about this ?
Alright, after some playing around and what not, I have a solution. I used this article to come to this solution.I use StyleCop, so you'll need to get and install that. Then, you can download my C# project MathematicsAnalyzer.
First off, I did not account for all type conversion mismatches. In fact, I only accommodate one part.
Basically, I check to see if the line contains "double" followed by a space. I do know that could lead to false warnings, because the end of a class could be double or any number of other things, but I'll leave that to you to figure out how to properly isolate the type.
If a match is found, I check to see that it matches this regex:
double[ ][A-Za-z0-9]*[ ]?=(([ ]?[0-9]*d[ ]?/[ ]?[0-9]*;)|[ ]?[0-9]*[ ]?/[ ]?[0-9]*d;)
If it does -not- match this regex, then I add a violation. What this regex will match on is any of the following:
double i=4d / 100;
double i = 4d / 100;
double i = 4 / 100d;
double i = 4/ 100d;
double i = 4 /100d;
double i = 4/100d;
double i=4d / 100;
double i=4 / 100d;
double i=4/100d;
Any of the above will not create a violation. As it is currently written, pretty much if a 'd' isn't used, it'll throw a violation. You'll need to add extra logic to account for the other possible ways of explicitly casting an operand. As I'm writing this, I've just realized that having a 'd' on both operands will most likely throw an exception. Whoops.
And lastly, I could not get StyleCop to display my violation properly. It kept giving me an error about the rule not existing, and even with a second pair of eyes on it, we could not find a solution, so I hacked it. The error shows the name of the rule you were trying to find, so I just put the name of the rule as something descriptive and included the line number in it.
To install the custom rule, build the MathematicalAnalyzer project. Close Visual Studio and copy the DLL into the StyleCop install directory. When you open Visual Studio, you should see the rule in the StyleCop settings. Step 5 and 6 of the article I used shows where to do that.
This only gets one violation at a time throughout the solution, so you'll have to fix the violation it shows, and run StyleCop again to find the next one. There may be a way around that, but I ran out of juice and stopped here.
Enjoy!
This article explains how to set up custom Code Analysis rules that, when you run Code Analysis, can show warnings and what not.
http://blog.tatham.oddie.com.au/2010/01/06/custom-code-analysis-rules-in-vs2010-and-how-to-make-them-run-in-fxcop-and-vs2008-too/

Why does C# let me overflow without any error or warning when casting an Int64 to an Int32 and how does it do the cast?

This question stems from a bug where I iterated over a collection of Int64 and accidentally did foreach (int i in myCollection). I was trying to debug the baffling problem of how when I did a linq query, i was not part of the myCollection.
Here's some code that surprised me:
Int64 a = 12345678912345;
Console.Write((int)a);
I expected the compiler to give me an error. The usual one is that an implicit cast does not exist. But no, it didn't mind this at all. Not even a warning!
The outputted value of (int)a incidentally is 1942903641.
I'm curious to know why the cast is permitted without any warnings and also how it comes up with that value. Any ideas?
By default, conversions like this are not checked. You'd have to ask for it explicitly:
Console.Write(checked((int)a)); // Kaboom!
Checked conversions can be globally enabled by the C# compiler's /checked option. That the project templates do not turn this option on for the Debug build is an oversight in my book, overflows can be drastically hard to diagnose.
Nothing you can't fix however, simply use Project > Properties > Build tab > Advanced button > tick the "Check for arithmetic overflow/underflow" option. And note how your foreach loop now bombs with an OverflowException. Do keep in mind that you'll be staring it at for a couple of minutes when it happens :) It is not a very cheap check so you'll want to leave it off for the Release build.
By default, C# does not check for overflows when processing numbers. This includes things like wrapping from int.MaxValue to int.MinValue in addition and multiplication, and when you cast longs to ints. To control this, use the checked and unchecked keywords, or the /checked compiler option.
The value 1942903641 is the result when your long is truncated to an int. It comes from the 32 least significant bits of the long value, taken as a two's complement signed integer.
When using foreach, it's important to know that if you declare a type that doesn't match the type of the enumerable, it will treat it as if you casted to that type. foreach (int i in myCollection) compiles to something like int i = (int)myEnumerator.Current;, not int i = myEnumerator.Current;. You could use foreach (var i in myCollection) to avoid such mistakes in the future. var is recommended to use for the loop variable in for and foreach statements.
You can see the results of various things in the following example (hexadecimal output is used to show the truncation more clearly: they have the same ending digits, the int just lacks some of the more significant digits):
checked
{
Int64 a = 12345678912345;
Console.WriteLine(a.ToString("X"));
Console.WriteLine((a % ((long)uint.MaxValue + 1L)).ToString("X"));
try
{
Console.WriteLine(((int)a).ToString("X")); // throws exception
}
catch (Exception e)
{
Console.WriteLine("It threw! " + e.Message);
}
}
unchecked
{
Int64 a = 12345678912345;
Console.WriteLine(a.ToString("X"));
Console.WriteLine((a % (long)Math.Pow(2, 32)).ToString("X"));
Console.WriteLine(((int)a).ToString("X"));
}
This outputs:
B3A73CE5B59
73CE5B59
It threw! Arithmetic operation resulted in an overflow.
B3A73CE5B59
73CE5B59
73CE5B59
By default overflow checking is turned off for integral-type arithmetic operations.
You can enable it by putting your code into "checked" section:
Int64 a = 12345678912345;
checked
{
Console.Write((int)a);
}
You can achieve the same thing by changing your compiler options.
In modern versions of VS (since VS 2003 or so?) the arithmetic overflow/underflow check is turned off by default.
You can change this in project's properties -> build -> advanced -> "Check for arithmetic overflow/underflow".
The reason the foreach hides that a cast occurs is because it originated in C# 1 - before generics.
It's defined as (Section 8.8.4 of the C# language specification v5):
A foreach statement of the form
foreach (V v in x) embedded-statement
is then expanded to:
{
E e = ((C)(x)).GetEnumerator();
try {
while (e.MoveNext()) {
V v = (V)(T)e.Current;
embedded-statement
}
}
finally {
… // Dispose e
}
}
As you can see, the foreach automatically gains an explicit cast on that first line.
Your value 12345678912345 gets truncated to a 32-bit integer. It's easier to understand in in hexadecimal:
12345678912345 in base 10 is b3a73ce5b59 in hexadecimal.
b3a73ce5b59 truncated to 32 bits is 73ce5b59 (keep the least significant 8 hexadecimal digits).
73ce5b59 in hexadecimal is 1942903641 in base 10.
As to why you do not get any errors or warnings:
Your conversion does not involve a compile-time constant, so the compiler will not do any static checks (in this simple case, it could, but not in general).
By default, C#'s long to int explicit conversion generates the conv.i4 CIL instruction, which truncates the value without throwing exceptions on overflow. Using a checked statement or expression, or compiling with the /checked switch will make the C# compiler emit the conv.ovf.i4 instead, which does throw exceptions on overflow.

Why adding two large integers whose result greater than int.MaxValue doesn't throw overflow exception?

If we are using the following loop in a program, the loop never ends in C# 4.0
for (int i = 1; i <= int.MaxValue; i++)
{
}
This is because adding 1 to int.MaxValue (2147483647) will not result in an overflow exception, but results in -2147483648 (taking into consideration 32bit int and 2's compliment).
int i = int.MaxValue;
Console.WriteLine(i + 1);
It seems the behavior changed recently. See the question Arithmetic operation caused OverflowException .What could be the reason behind this change?
Overflow exceptions for integer (and other integral types) are only done in checked contexts.
So, this will cause an exception:
checked
{
int i = int.MaxValue;
Console.WriteLine(i + 1);
}
They are not set to do this by default as they are more expensive than simply overflowing.
From MSDN:
The checked keyword is used to explicitly enable overflow checking for integral-type arithmetic operations and conversions.
And:
Overflow checking can be enabled by compiler options, environment configuration, or use of the checked keyword.
This is not a recent change - C# has been like this from day one. What you see in the question is VB.NET code, which is by default in a checked context.
So, keeping to defaults, overflowing code in VB.NET will throw an exception, but identical code in C# will not.

No overflow exception for int in C#?

I had this weird experience with problem number 10 on Project Euler (great site by the way). The assignment was to calculate the sum of all the prime numbers below two million.
I used an int for the sum, and my algorith produced an answer, but when i pasted it to verify the answer, it was wrong.
It turned out that the result was too big to fit in an int, but wouldn't this cause an overflow error or something? Instead, it just returned a value far off from the real answer.
When I changed the type to long, everything was hunky dory.
C# integer operations don’t throw exceptions upon overflow by default. You can achieve that via the project settings, or by making the calculation checked:
int result = checked(largeInt + otherLargeInt);
Now the operation will throw.
The opposite is unchecked, which makes any operation explicitly unchecked. Obviously, this only makes sense when you’ve got checked operations enabled in the project settings.
In C# an OverflowException is not thrown (in VB the exception is thrown per default).
To get the excpetion you have to embed your code in a checked context:
byte value = 241;
checked
{
try
{
sbyte newValue = (sbyte) value;
Console.WriteLine("Converted the {0} value {1} to the {2} value {3}.",
value.GetType().Name, value,
newValue.GetType().Name, newValue);
}
catch (OverflowException)
{
Console.WriteLine("Exception: {0} > {1}.", value, SByte.MaxValue);
}
}
MSDN explains in more detail:
For the arithmetic, casting, or
conversion operation to throw an
OverflowException, the operation must
occur in a checked context. By
default, arithmetic operations and
overflows in Visual Basic are checked;
in C#, they are not. If the operation
occurs in an unchecked context, the
result is truncated by discarding any
high-order bits that do not fit into
the destination type.
It's because, by default C# do not throw any exception for integer overflow as well as underflow. There are couple of things you can do here.
Option 1
You have to enable the exception to be thrown by go to
Project => properties => Build tab => Advanced => check for arithmetic overflow underflow.(make sure you tick the option)
Make sure you tick the option
Option 2
Use a checked block and throw an overflow exception to handle the situation. A sample code snippet would be
try
{
checked
{
int y = 1000000000;
short x = (short)y;
}
}
catch (OverflowException ex)
{
MessageBox.Show("Overflow");
}
catch (Exception ex)
{
MessageBox.Show("Error");
}
I have already added a comment, but maybe it would be interesting for some of you:
msdn tells us:
Integer arithmetic overflow either
throws an OverflowException or
discards the most significant bits of
the result
but
Decimal arithmetic overflow always
throws an OverflowException.
also
When integer overflow occurs, what
happens depends on the execution
context, which can be checked or
unchecked. In a checked context, an
OverflowException is thrown. In an
unchecked context, the most
significant bits of the result are
discarded and execution continues.
Thus, C# gives you the choice of
handling or ignoring overflow.
By default, C# does not check for arithmetic overflow on integers. You can change this with the /checked compiler option or by enabling "Check for arithmetic overflow/underflow" in Visual Studio (project properties - Build - Advanced).
You can use checked and unchecked keywords to override the default on a case-by-case basis. If you rely on checking taking place in a piece of code, explicitly enabling it using checked would be a good idea.
int j = checked(i * 2);
checked
{
int j = i * 2;
// Do more stuff
}
Note that floating point operations never throw an OverflowException, and decimal operations always throw an OverflowException. See also C# operators.
You can set checked directly in csproj by adding:
<PropertyGroup>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
</PropertyGroup>
It's the equivalent of ticking that Check for arithmetic overflow/underflow checkbox in the designer.

Break into C# debugger for divide by zero

I'm using C# with the XNA library and I'm getting NaNs cropping up in my Vector3 objects. Is there a way to break into the debugger when the offending calculation happens (e.g. a divide by zero)? Currently the program just continues running. I'm using VS2008 Professional. All the exceptions in the Exceptions dialog are selected in the "user-unhandled" column.
Edit: To clarify, I can't work out where the bad calculation is. This is why I want the debugger to break automatically. Setting breakpoints is not a solution.
Firstly dividing a double/float by zero gives Infinity/-Infinity depending upon whether the double is positive or negative. Only a zero double/float divided by zero gives NaN. In either case, no exception will be thrown.
You should be able to use conditional breakpoints to detect when a particular variable gets set to one of these values. Be careful when checking for NaN though, as NaN != NaN.
double a = double.NaN;
Console.Out.WriteLine(a == double.NaN); // false
Console.Out.WriteLine(a == a); // false
Console.Out.WriteLine(double.IsNaN(a)); // true
Sounds like you're handling the exception somehow (like a catching a generic Exception) What you can do is press Ctrl+alt+E to bring up the exceptions dialog -- make sure you check the "when thrown" checkbox for the exception(s) you're interested in
You could set a conditional breakpoint that only breaks when the divisor of an expression is 0.
I know this is an old post but.....
from experience its nearly always Vector3.Normalize that i use by mistake.
When I'm not sure whether it will be zero length I now always do
float L = V.Length();
if(L != 0.0)
V /= L;
divide by zero in Normalize should give an exception but it doesn't. Caused me a lot of head scratching.

Categories