Answered by:
"Arithmetic operation resulted in an overflow." error in VB code but not in C# code
Question
-
Hi,
I have an application in which I am communicating with a 2d profiler (generates a data array from a 2d CMOS sensor, like a camera, except that is uses triangulation with a laser line to detect height variances due to the location of the reflected light which changes along one direction (columns) of the sensor based on the distance from the object at the point of reflection to the face of the laser/sensor pair). The methodology is that the sensor rows represent points along the length of the laser stripe, while the columns return the corresponding position of the reflected light (analogous to the object to sensor distance), hence, a 2d scan.
The data are returned to an array and processed for drawing into a picture box, representing this 2d profile.
My issue is this. I have C# code which works fine, and a converted equivalent in VB which gives the exception "Arithmetic operation resulted in an overflow."
The problem seems to be with the array ==> mem_read_commnad. I have determined this by commenting out the statements where these are set, one by one.
Elements mem_read_commnad[6] and mem_read_commnad[7] seem to be the culprits, however, I would think that the array itself is generating the wrong values, which are precipitating the erroneous values.
A copy of the source code and pertinent values obtained for each version follows:
C# Version
VALUES OBTAINED:
mem_read_commnad ==> {2, 3, 0, 2, 0, 0, 0, 0, 0, 17, 3, 0}
recv_data ==> {2, 2, 64, 11, 0, 122, 208, 0, 3, 227, 0, 0, 0, 0, 0}
a = address = 8048640 (first time through loop)
CODE:
private void getProfileButton_Click(object sender, EventArgs e)
{
try
{
int tc = Environment.TickCount;
var recv_data = new byte[255 * 2 + 6];
//Getting latest profile address
var get_naddr_command = new byte[] { STX, 0, 0x40, 0x0B, ETX, 0 };
get_naddr_command[5] = calc_bcc(get_naddr_command);
serialPort1.Write(get_naddr_command, 0, 6);
WaitReply(recv_data, 10);
int address = (recv_data[4] << 24) + (recv_data[5] << 16) + (recv_data[6] << 8) + recv_data[7];
int nwords = 10000;
int a = address;
int j = 0;
for (; nwords > 0; )
{
int n;
if (nwords <= 253)
n = nwords;
else
n = 253;
var mem_read_commnad = new byte[12] { STX, 3, 0x00, 0x02, 0, 0, 0, 0, 0, 0x11, ETX, 0 };
mem_read_commnad[4] = (byte)(a >> 24);
mem_read_commnad[5] = (byte)(a >> 16);
mem_read_commnad[6] = (byte)(a >> 8);
mem_read_commnad[7] = (byte)(a);
mem_read_commnad[8] = (byte)n;
mem_read_commnad[11] = calc_bcc(mem_read_commnad);
serialPort1.Write(mem_read_commnad, 0, 12);
int ret = WaitReply(recv_data, 255 * 2 + 6);
if (nwords > 9999)
{
ushort w0 = (ushort)((recv_data[8] << 8) | recv_data[9]);
profile_size = (w0 >> 5);
nwords = profile_size * 2 + 2;
}
for (int i = 0; i < n; i++)
{
profile[j++] = (short)((recv_data[8 + 2 * i] << 8) + recv_data[9 + 2 * i]);
//profile[j++] = (short)((recv_data[10+4*i]<<8) + recv_data[11+4*i]);
}
nwords -= n;
a += n;
}
profileImage.Refresh();
}
catch (Exception ex)
{
intervalProfile.Checked = false;
MessageBox.Show(ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}VB Version
VALUES OBTAINED:
mem_read_commnad ==> {2, 3, 0, 2, 0, 0, 0, 0, 0, 17, 3, 0}
recv_data ==> {2, 2, 64, 11, 0, 142, 64, 0, 3, 135, 0, 0, 0, 0, 0}
a = address = 9322496 (first time through loop)
CODE:
Private Sub getProfileButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles getProfileButton.Click
Try
Dim tc As Integer = Environment.TickCount
Dim recv_data = New Byte((255 * 2 + 6) - 1){}
'Getting latest profile address
Dim get_naddr_command = New Byte() { STX, 0, &H40, &HB, ETX, 0 }
get_naddr_command(5) = calc_bcc(get_naddr_command)
serialPort1.Write(get_naddr_command, 0, 6)
WaitReply(recv_data, 10)
Dim address As Integer = (CInt(recv_data(4)) << 24) + (CInt(recv_data(5)) << 16) + (CInt(recv_data(6)) << 8) + recv_data(7)
Dim nwords As Integer = 10000
Dim a As Integer = address
Dim j As Integer = 0
Do While nwords > 0
Dim n As Integer
If nwords <= 253 Then
n = nwords
Else
n = 253
End If
Dim mem_read_commnad = New Byte(11) { STX, 3, &H0, &H2, 0, 0, 0, 0, 0, &H11, ETX, 0 }
mem_read_commnad(4) = CByte(a >> 24)
mem_read_commnad(5) = CByte(a >> 16)
mem_read_commnad(6) = CByte(a >> 8)
mem_read_commnad(7) = CByte(a)
mem_read_commnad(8) = CByte(n)
mem_read_commnad(11) = calc_bcc(mem_read_commnad)
serialPort1.Write(mem_read_commnad, 0, 12)
Dim ret As Integer = WaitReply(recv_data, 255 * 2 + 6)
If nwords > 9999 Then
Dim w0 As UShort = CUShort((CInt(recv_data(8)) << 8) Or recv_data(9))
profile_size = (CInt(w0) >> 5)
nwords = profile_size * 2 + 2
End If
For i As Integer = 0 To n - 1
profile(j) = CShort((CInt(recv_data(8 + 2 * i)) << 8) + recv_data(9 + 2 * i))
j += 1
'profile[j++] = (short)((recv_data[10+4*i]<<8) + recv_data[11+4*i]);
Next i
nwords -= n
a += n
Loop
profileImage.Refresh()
Catch ex As Exception
intervalProfile.Checked = False
MessageBox.Show(ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
End Try
End Sub
Any ideas would be greatly appreciated!!!
Thanks!
Wednesday, August 13, 2014 8:34 PM
Answers
-
Hello,
In C# Checked and Unchecked is used.
string Test = "2147483647"; int Value = Convert.ToInt32(Test); int Result = unchecked(Value + 2); if (Result >0) { Console.WriteLine("Positive"); } else { Console.WriteLine("Negative"); }Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem.
- Marked as answer by Franklin ChenMicrosoft employee Thursday, August 21, 2014 12:41 PM
Wednesday, August 13, 2014 9:17 PM -
By default, C# does not check for integer overflow while VB does.
You can change this in the projects settings for your VB project. On the Compile Tab, click the "Advanced Compile Options" button. On that dialog, check the box called "Remove integer overflow checks"
By the way, the array recv_data seems to have different values in the VB version when compared to the C# version. Is that intentional?
- Edited by Chris Dunaway Wednesday, August 13, 2014 8:45 PM
- Proposed as answer by Franklin ChenMicrosoft employee Thursday, August 14, 2014 6:57 AM
- Marked as answer by Franklin ChenMicrosoft employee Thursday, August 21, 2014 12:41 PM
Wednesday, August 13, 2014 8:40 PM
All replies
-
By default, C# does not check for integer overflow while VB does.
You can change this in the projects settings for your VB project. On the Compile Tab, click the "Advanced Compile Options" button. On that dialog, check the box called "Remove integer overflow checks"
By the way, the array recv_data seems to have different values in the VB version when compared to the C# version. Is that intentional?
- Edited by Chris Dunaway Wednesday, August 13, 2014 8:45 PM
- Proposed as answer by Franklin ChenMicrosoft employee Thursday, August 14, 2014 6:57 AM
- Marked as answer by Franklin ChenMicrosoft employee Thursday, August 21, 2014 12:41 PM
Wednesday, August 13, 2014 8:40 PM -
Chris,
Thank you!!! This did it.
BTW, the values recv_data value contains the sensor result data, which changes a bit from scan to scan, depending on the lighting and movement of the setup. The unit is not very well secured on the bench, but will be in the system.
Do you know why "remove integer overflow checks" is required in VB but not C#? I know the these differ a bit in how data types are handled/processed, but not sure about this issue. Also, is there any penalty with removing the checks?
Thanks, again!
Wednesday, August 13, 2014 9:08 PM -
Hello,
In C# Checked and Unchecked is used.
string Test = "2147483647"; int Value = Convert.ToInt32(Test); int Result = unchecked(Value + 2); if (Result >0) { Console.WriteLine("Positive"); } else { Console.WriteLine("Negative"); }Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem.
- Marked as answer by Franklin ChenMicrosoft employee Thursday, August 21, 2014 12:41 PM
Wednesday, August 13, 2014 9:17 PM -
Do you know why "remove integer overflow checks" is required in VB but not C#? I know the these differ a bit in how data types are handled/processed, but not sure about this issue. Also, is there any penalty with removing the checks?
I don't know why that option is checked by default in VB. Perhaps Microsoft chose that as the default because it's the safest option when converting older VB6 code.
Friday, August 15, 2014 8:42 PM