iBent
iBent

Reputation: 402

C++ Array out of Range access to calculate pointer valid?

Is the following code guaranteed to be working?

int* arr = new int[2];
std::cout << &arr[0x100];

Is this considered good practice or would it be cleaner to add an offset the regular way?

Edit: By "working" I mean that it should print the pointer to the theoretical member at 0x100. Basically if this is equivalent to "std::cout << ((unsigned int)arr + 0x100*sizeof(int));".

Upvotes: 3

Views: 639

Answers (2)

Ernie Mur
Ernie Mur

Reputation: 571

In the first line you allocate 2 integer values. In the second line, you access memory outside this range. This is not allowed at all.

Edit: Some interesting comments here. But I cannot understand, why it should be needed to cite the standard for such a simple answer and why is pointer arithmetic discussed here so much?

From a logical view, std::cout << &arr[0x100] consists of 3 steps: 1. access the non existing member of an array 2. get the address of the non existing member 3. use the address of the non existing member

If the first step is invalid, aren't all the following undefined?

Upvotes: 0

9Breaker
9Breaker

Reputation: 724

With my compiler (Cygwin GCC) getting the address at this value is the same as doing pointer arithmetic, although each is undefined behavior (UB). As mentioned in the comment below by Jens, at http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html, I found the following helpful.

It is also worth pointing out that both Clang and GCC nail down a few behaviors that the C standard leaves undefined. The things I'll describe are both undefined according to the standard and treated as undefined behavior by both of these compilers in their default modes.

Dereferences of Wild Pointers and Out of Bounds Array Accesses: Dereferencing random pointers (like NULL, pointers to free'd memory, etc) and the special case of accessing an array out of bounds is a common bug in C applications which hopefully needs no explanation. To eliminate this source of undefined behavior, array accesses would have to each be range checked, and the ABI would have to be changed to make sure that range information follows around any pointers that could be subject to pointer arithmetic. This would have an extremely high cost for many numerical and other applications, as well as breaking binary compatibility with every existing C library.

The pointer arithmetic is also UB. So you have an address, but you cannot dereference the pointer to it. So there is really no use in having this address at all. Just getting the address is UB and should not be used in code.

See this answer for out-of-bounds pointers: Why is out-of-bounds pointer arithmetic undefined behaviour?

My sample code:

    int* arr = new int[2];
    std::cout << arr << std::endl;
    std::cout << &(arr[0])<< std::endl;
    std::cout << &(arr[1])<< std::endl;
    std::cout << &arr[0x100] << std::endl; // UB, cannot be dereferenced
    std::cout << &arr[256] << std::endl;   // cannot be dereferenced, so no use in having it
    std::cout << arr + 0x100; // UB here too, no use in having this address 

Sample Output:

0x60003ae50
0x60003ae50
0x60003ae54
0x60003b250
0x60003b250
0x60003b250

Upvotes: 1

Related Questions