When compiled for 64bit the following code crashes with an access violation when accessing ptr[1-offset]:
char* ptr = new char[4];
strcpy(ptr, "bar");
unsigned int offset = 2;
ptr+=offset;
char test0 = (ptr-offset)[2];
char test1 = ptr[2-offset];
char test2 = (ptr-offset)[1];
char test3 = ptr[1-offset];
delete (ptr-offset);
The code executes just fine when compiled for 32bit.
When I replace ptr[1-offset] by ptr[(int)(1-offset)] or alternatively when I change unsigned int offset = 2; into int offset = 2; the code executes just fine for 64bit, too.
Apparently on 64bit the result of 1-offset gets promoted to an unsigned integer type, so that ptr[1-offset] does not resolve to ptr[-1], but to ptr[maxValueOfSomeUnsignedIntegerType].
However, why does this only happen for 64bit, while 1-offset appears to get promoted to a signed integer type for 32bit?
This seems not to be implementation specific - I get the same results with VC++ and with G++.
First of all, the result of 1-offset is always UINT_MAX, independent of your architecture. This alone does not explain the difference.
If you cast that to int, you get an implementation defined result, but that usually is -1. Same thing with int offset, you just get normal signed integer arithmetic that results in -1. So that works.
Now for why the segfault: Apparently, on the systems you tried, overflowing arithmetic on pointers wraps mod 2^32. As far as I know this is UB, but it seems to work on your systems. So you effectively end up with ptr[1].
On the other hand, if the pointer is 64 bits wide, it can represent ptr + 2^32 - 1 (at least in this case apparently), so no wrapping happens and the pointer points to some nonsense location about 4GB after what you allocated.
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