Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Maximum valid memory address

Tags:

c++

pointers

I often see code that adds a value, such as a length to a pointer, and then uses this value, e.g.

T* end = buffer + bufferLen;//T* + size_t

if (p < end)

However, is it possible for the buffer to have been allocated near enough the end of memory that "buffer + bufferLen" may overflow (e.g. 0xFFFFFFF0 + 0x10), resulting in "p < end" being false even if p was a valid element address (e.g. 0xFFFFFFF8).

If it is possible, how can it be avoided when I see many things that work with a begin/end range where end next element after the last one

like image 709
Fire Lancer Avatar asked Aug 20 '12 12:08

Fire Lancer


People also ask

How big is a memory address in C?

Memory addresses are 32-bits long on most CPUs today, although there is a increasing trend toward 64-bit addressing). The location of i has a specific address, in this case 248,440. The pointer p holds that address once you say p = &i;. The variables *p and i are therefore equivalent.

How big is a memory address?

Each address identifies a single byte (eight bits) of storage. Data larger than a single byte may be stored in a sequence of consecutive addresses.

Is 0 a valid memory address?

Memory address 0 is called the null pointer. Your program is never allowed to look at or store anything into memory address 0, so the null pointer is a way of saying "a pointer to nothing".


2 Answers

From the standard:

c++11

5.9 Relational operators [expr.rel]

If two pointers point to elements of the same array or one beyond the end of the array, the pointer to the object with the higher subscript compares higher.

So you don't need to worry; a conformant implementation will ensure that the past-the-end pointer compares correctly to the rest of the array. In addition,

3.7.4.1 Allocation functions [basic.stc.dynamic.allocation]

[...] The pointer returned shall be suitably aligned so that it can be converted to a pointer of any complete object type with a fundamental alignment requirement (3.11) and then used to access the object or array in the storage allocated [...]

The implication is that the pointer returned should be able to be treated as the pointer to the beginning of an array of appropriate size, so 5.9 continues to hold. This would be the case if the allocation function call is the result of calling operator new[] (5.3.4:5).

As a practical matter, if you're on a platform where it is conceivable for the allocator to (non-conformantly) return a block of memory ending at 0xFFFFFFFF, you could in most cases write

if (p != end)
like image 75
ecatmur Avatar answered Oct 19 '22 23:10

ecatmur


It is not possible for elements of a contiguous memory allocation to have non-contiguous addresses. end always has an address of higher value than start.

In the case that the allocation happens to end at exactly 0xFFFFFFFF for example, meaning end will be 0x00000000, this would be a bug and the code should be fixed to accommodate that scenario.

On some platforms though this scenario is impossible by design and could be a reasonable compromise in logic for the sake of simplicity. For example I would not hesitate to write if(p < end) on a Windows user-mode application.

like image 31
tenfour Avatar answered Oct 20 '22 00:10

tenfour