Now filed on Microsoft Connect; please upvote if you feel it needs fixing. I've also simplified the test case a lot:
byte* data = (byte*) 0x76543210;
uint offset = 0x80000000;
byte* wrong = data + offset;
byte* correct = data + (uint) 0x80000000;
// "wrong" is now 0xFFFFFFFFF6543210 (!)
// "correct" is 0xF6543210
Looking at the IL, as far as I can tell, the C# compiler did everything right, and the bug lies in the JITter.
Original question: What is going on here?
byte* data = (byte*)Marshal.AllocHGlobal(0x100);
uint uioffset = 0xFFFF0000;
byte* uiptr1 = data + uioffset;
byte* uiptr2 = data + (uint)0xFFFF0000;
ulong uloffset = 0xFFFF0000;
byte* ulptr1 = data + uloffset;
byte* ulptr2 = data + (ulong)0xFFFF0000;
Action<string, ulong> dumpValue =
(name, value) => Console.WriteLine("{0,8}: {1:x16}", name, value);
dumpValue("data", (ulong)data);
dumpValue("uiptr1", (ulong)uiptr1);
dumpValue("uiptr2", (ulong)uiptr2);
dumpValue("ulptr1", (ulong)ulptr1);
dumpValue("ulptr2", (ulong)ulptr2);
This test requires a 64-bit OS targeting the x64 platform.
Output:
data: 000000001c00a720 (original pointer) uiptr1: 000000001bffa720 (pointer with a failed carry into the higher dword) uiptr2: 000000011bffa720 (pointer with a correct carry into the higher dword) ulptr1: 000000011bffa720 (pointer with a correct carry into the higher dword) ulptr2: 000000011bffa720 (pointer with a correct carry into the higher dword) ^ look here
So is this a bug or did I mess something up?
I think you are encountering this C# compiler bug: https://connect.microsoft.com/VisualStudio/feedback/details/675205/c-compiler-performs-sign-extension-during-unsigned-pointer-arithmetic
Which was filed as a result of this question: 64-bit pointer arithmetic in C#, Check for arithmetic overflow changes behavior
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With