Code in C#:
address = glowObject + (glowIndex * 0x38) + 0x4;
Code in VB:
address = glowObject + (glowIndex * &H38) + &H4
I inserted a breakpoint on that line in both my C# code and VB code.
The values were the same in both.
C#: Breakpoint:
VB Breakpoint:
So it looks like my VB code is getting the result, but it's still throwing an exception on that line of code.
What could be causing this?
In C#, arithmetic operations are unchecked by default, which means that arithmetic overflow is not checked at runtime. You can control this with the checked/unchecked keywords, and/or with the /checked compiler option.
In VB.NET, arithmetic operations are checked by default.
In your code, the result overflows the capacity of an int; in C#, it overflows silently, producing an incorrect result, whereas in VB.NET, it throws an exception. In either case, your code has a bug...
Found the solution :)
It was as simple as checking a box in the compiler options.
Thank you to Thomas Levesque for telling me about the compiler option.
Go to the compile tab in your project settings, click on Advanced Compiler Settings, and check the "Remove integer overflow checks"
Related
I was tinkering with IP packet 'parsers' when I noticed something odd.
When it came to parsing the IP addresses, in C#
private uint srcAddress;
// stuff
srcAddress = (uint)(binaryReader.ReadInt32());
does the trick, so you'd think this VB.Net equivallent
Private srcAddress As UInteger
'' stuff
srcAddress = CUInt(binaryReader.ReadInt32())
would do the trick too. It doesn't. This :
srcAddress = reader.ReadUInt32()
however will.
Took some time to discover, but what have I dicovered -- if anything ? Why is this ?
VB.NET, by default, does something that C# doesn't do by default. It always check for numerical overflow. And that will trigger in your code, IP addresses whose last bit is 1 instead of 0 will produce a negative number and that cannot be converted to UInteger. A data type that can only store positive 32-bit numbers.
C# has this option too, you'd have to explicitly use the checked keyword in your code. Or use the same option that VB.NET projects have turned on by default: Project + Properties, Build tab, Advanced, tick the "Check for arithmetic overflow/underflow" checkbox. The same option in VB.NET project is named "Remove integer overflow checks", off by default.
Do note how these defaults affected the syntax of the languages as well. In C# you have to write a cast to convert a value to an incompatible value type. Not necessary in VB.NET, the runtime check keeps you out of trouble. It is very bad kind of trouble to have, overflow can produce drastically bad results. Not in your case, that happens, an IP address really is an unsigned number.
Do keep the other quirk about IP-addresses in mind, sockets were first invented on Unix machines that were powered by LSD and big-endian processors. You must generally use IPAddress.NetworkToHostOrder() to get the address in the proper order. Which only has overloads that take a signed integer type as the argument. So using ReadInt32() is actually correct, assuming it is an IPv4 address, you pass that directly to NetworkToHostOrder(). No fear of overflow.
I have made a calculator with C# (in VS 2008), but I can't understand why the
checked{iCurrent = (iCurrent * 10) + i;}
can check the overflow, can someone explain this? Thanks.
This is my code:
try
{
//get the typed
long iCurrent=long.Parse(textOut.Text);
if(bNumBegins)
{
iCurrent = i;
bNumBegins = false;
}
else
{
//check whether overflow
checked{iCurrent = (iCurrent * 10) + i;}
}
textOut.Text = iCurrent.ToString();
}
When you use the checked keyword you ask the compiler to automatically generate code that will test whether overflow has occurred after arithmetic operations. If overflow is detected, an OverflowException is thrown.
The default in C# is to not check for such overflow when performing arithmetic operations. The default can be changed to check all operations. Regardless of the default, the checked and unchecked keywords can be used to selectively check or ignore overflow as needed.
#DavidPilkington Yes, why need * 10? Thanks
I think that you are confused here.
The code is multiplying the iCurrent variable by 10 and then adding one. This is the desired effect that the coder wanted. The checked keyword is used to make sure that there is no OverflowException.
The *10 is not needed for the checked, the check is "needed" for the operation to ensure that the number is not too large.
Here is the MSDN documention on checked. I suggest you read through it and the examples to gain a better understanding.
I'm currently reading through C# 4.0 In A Nutshell, and in chapter 2 it states that if an int object has a value of int.MinValue (-2147483648) and the value is decreased, as the value cannot go any lower, it goes to the highest value, int.MaxValue (2147483647):
int a = int.MinValue;
Console.WriteLine(a); //-2147483648
a = a-1;
Console.WriteLine(a); //-2147483648
Console.WriteLine (a == int.MaxValue); // True
The book then goes on to mention how you can protect from this happening using checked.
However, I'm wondering why this is possible? Surely this could cause a lot of issues if its not protected with checked?
Is it not a bit of a flaw in the design? Why would anyone want a minimum value to become a maximum value?
Furthermore, I've noticed VB.NET will throw an 'Arithmetic overflow' instead of letting this happen:
Dim a As Integer
a = Integer.MaxValue
a = a + 1
Response.Write(a) 'Arithmetic overflow exception here
Sometimes it is desired behaviour. Other times, it simply isn't necessary to deal with and check for overflows, as they slow down program execution. Take a game drawing unbound (FPS). At 1000FPS, a small 1ms extra check could have a significant affect on framerate. Other times, it may be expected execution (I've only seen one use of this to date) - it flows on from what happens in C#'s ancestor - C++ and C.
Also, please note that the default behaviour (checked or unchecked) varies between configurations and environments:
If neither checked nor unchecked is used, a constant expression uses
the default overflow checking at compile time, which is checked.
Otherwise, if the expression is non-constant, the run-time overflow
checking depends on other factors such as compiler options and
environment configuration.
Since the code you posted is non-constant (and also due to various environment variables), no checking for overflows is performed.
It is a matter of language design - why this happens has to do with the binary representation of numbers. In .NET this is done with two's complement, hence the overflow issue.
The designers of VB.NET have decided to not allow such overflow/underflow issues.
The designers of C# have decided to leave control to the programmer.
It is possible that your programm automatically check overflow: right click on project file,
select Build, than select Advanced button in right bottom corner. In the opened window check Check Arithmetical Overflow checkbutton.
I am accustomed to C# not performing overflow checks, as the language spec states (ยง7.5.12):
For non-constant expressions (expressions that are evaluated at run-time) that are not enclosed by any checked or unchecked operators or statements, the default overflow checking context is unchecked unless external factors (such as compiler switches and execution environment configuration) call for checked evaluation.
I took advantage of this when doing an array bounds check in low-level code:
if ((uint)index >= (uint)TotalCount)
...
If index is negative, I expect it to become a large positive number so that it exceeds TotalCount. However, to my surprise, a negative number produces OverflowException, and I have to wrap the expression in unchecked(). I looked through the project options in Visual Studio and I do not see an option to enable or disable overflow checking. So why might it be on here?
It should be in the project.
Double click the Properties folder.
Build tab.
Click the Advanced... button.
Uncheck "Check for arithmetic overflow/underflow".
Consider the following piece of code:
As you can see we are on line 28. Is there any way to see the return value of the function at this point, without letting the code return to the caller function?
Foo.Bar() is a function call which generates a unique path (for example). So it's NOT constant.
Entering ?Foo.Bar() in the immidiate window doesn't work either, since that reevaluates the code:
?Foo.Bar()
"80857466"
?Foo.Bar()
"2146375101"
?Foo.Bar()
"1106609407"
?Foo.Bar()
"792759112"
In VB.NET it's possible by entering the function's name in the Watch, which will then threat it as a variable.
But in C# this is not possible, any other tips?
PS: rewriting is not an option.
Answer found here: VS get returned value in C# code?
It is actually visible. Debug + Other
Windows + Registers. Look at the value
of EAX (RAX in x64). The value of
simple integral types are returned in
the EAX register. Long in EDX:EAX.
Floating point in STx (XMM00 in x64).
Assuming you are using visual studio, you could use the Immediate window. If you type Foo.Bar(); in the Immediate window you will get the result you are after, if you don't want it to re-evaluate stick a break point in the appropriate spot IE either before it evaluates the first time or in Foo.Bar() itself.