I have some unsafe C# code that does pointer arithmetic on large blocks of memory on type byte*, running on a 64-bit machine. It works correctly most of the time but when things get large I often get some kind of corruption where the pointer gets incorrect.
The strange thing is that if I turn on “Check for arithmetic overflow/underflow” everything works correctly. I do not get any overflow exceptions. But due to the large performance hit I need to run the code without this option.
What could be causing this difference in behavior?
It’s a C# compiler bug (filed on Connect). @Grant has shown that the MSIL generated by the C# compiler interprets the
uintoperand as signed. That’s wrong according to the C# spec, here’s the relevant section (18.5.6):You’re allowed to add a
uintto a pointer, no implicit conversion takes place. And the operation does not overflow the domain of the pointer type. So truncation is not allowed.