4

I did like to understand what is the difference between:

new IntPtr(pointer.ToInt64() + 0x4);

and

Marshal.ReadIntPtr(pointer + 0x4);

They give out a different result but does it not do the same thing?

If possible could you provide a practical example to illustrate what my misconception of it is?

Guapo
  • 3,446
  • 9
  • 36
  • 63
  • No. First is adding 4 to the address so 1000 + 4 = 1004. Second is a pointer to 32 bit number (4 bytes). So when you increment the pointer pointer you move 4 bytes at a time so 1000 + (4 x 4 bytes) = 1016. – jdweng Feb 17 '17 at 10:46
  • IntPtr is often used to store a memory address. The two statements are very different, the 1st one simply increments the address by 4. The 2nd does that as well, the quick way, *and* reads the memory. Presumably to retrieve a pointer value, an address stored in memory. – Hans Passant Feb 17 '17 at 12:12

1 Answers1

3

IntPtr is basically platform-specific integer. It's 32 bit in 32-bit OS and 64 bit in 64-bit OS. It's commonly used to represent a pointer, but can as well represent any random integer.

So your two methods do different things. First (IntPtr constructor) just takes whatever number you provide and represent that as IntPtr. In this case it does not matter if IntPtr is valid memory address or not.

Marshal.ReadIntPtr is doing different thing: it treats whatever you pass to it as memory address, then it goes to that address, reads 4 or 8 bytes from there, and returns IntPtr representing that data.

Try this to verify:

IntPtr pointer = IntPtr.Zero;
var anotherPointer = new IntPtr(pointer.ToInt64() + 0x4);
var yetAnother = Marshal.ReadIntPtr(pointer + 0x4);

This will throw memory access violation exception on third line, because you cannot read memory at such low address (0x4) usually. Second line however just returns whatever you passed there (4) as IntPtr.

Evk
  • 98,527
  • 8
  • 141
  • 191
  • Hi Evk thanks for the detailed answer, so basically you're telling me that `ReadIntPtr` would be something like doing `new IntPtr(new IntPtr(...).ToInt64)` skipping the validation or is that a wrong assumption? I mean in terms of equality from their description. Say we are on 32 bits for the sake of sanity. – Guapo Feb 17 '17 at 10:28
  • 1
    No, ReadIntPtr will read integer value from memory location you provide. So for example you provide 0x333333 there. It goes to the memory location 0x333333 and reads integer from there. It can be any integer. IntPtr constructor does not read anything from memory. Those two methods are completely different and are not related to each other at all. – Evk Feb 17 '17 at 10:30
  • I see, I was under the assumption IntPtr also reads it, thanks for the reply. In efficiency and not using unsafe, is Marhsal.ReadIntPtr the fastest or rather only option available or are there other options? if u don't mind replying to that as well in case u know. – Guapo Feb 17 '17 at 10:35
  • Well if you need to read integer value from pointer you either use unmanaged pointer (int*), use Marshal.ReadInt16 (or 32 or 64) (if you know what size this integer is) or use Marshal.ReadIntPtr (if you need platform-specific integer for some reason). No other options that I'm aware of. – Evk Feb 17 '17 at 10:40