4

In C++:

const size_t N = 1000;
int* p = new int[N];// time=t0

My program has just one thread and, after allocating memory to p, my program will just read the memory pointed by p.

What does the standard say about the value of p?

Will p keep the value it gets at time=t0 until a delete of p?

Or, can the OS decide on its own to reallocate the memory pointed by p?

Does it depend on the value of N?

Alessandro Jacopson
  • 18,047
  • 15
  • 98
  • 153
  • 7
    The value of a variable will never change on its own. – SLaks Aug 04 '14 at 18:27
  • 4
    Different things. `p` can keep it's value, *and* the memory pointed at by `p` can be re-allocated. – juanchopanza Aug 04 '14 at 18:28
  • @juanchopanza So can the OS decide on its own (without explicit code written by me) to re-allocate the memory? – Alessandro Jacopson Aug 04 '14 at 18:33
  • 1
    @uvts_cvs It could do, if you run out of memory or otherwise invoke undefined behaviour (UB). But the point (no pun intended) is that the pointer is just a variable that holds a number. That number won't just change by itself (unless you invoke UB, in which case all bets are off anyway.) – juanchopanza Aug 04 '14 at 18:35
  • 1
    Interesting question, I came back to this one because was curious if someone would find a standard quote to prove it. – Shafik Yaghmour Aug 07 '14 at 01:59

4 Answers4

5

The value of p cannot be moved around after it is created. The standard has made it useless to do so:

3.7.4.1 Allocation functions

...If the request succeeds, the value returned shall be a non-null pointer value (4.10) p0 different from any previously returned value p1, unless that value p1 was subsequently passed to an operator delete.

(end of citing the standard)


Therefore, if at run time, something decides to move p to another address for reasons such as consolidating some memory fragments, the standard has made it impossible for the space pointed by the original p being used by another memory allocation. The space will be wasted.

Yefu
  • 161
  • 2
1

The memory model and expected semantics of the standard speak about an observable behaviour which implementations must conform to (see paragraphs 1.7 - The C++ memory model - to 1.10 - Multi-threaded executions and data races - of the standard(1)). This observable behaviour shall match the one of the abstract machine described in the standard. It notably define memory of programs as a set of sequences of bytes, which may be modified through side effect operations (I/O on the memory). Pointers are themselves sequences of bytes stored in memory, and thus subjected to that same rule. The model also specifies situations of undefined behaviour, for which anything may happen, including memory corruption. Furthermore, a multithreaded program may, through race condition (see 1.10), modify memory "behind its own back" (my own wording, not an actual quote).

new operators works through the use of allocation functions, which return memory addresses, and must also comply to the rule of observable behaviour.

That being said, paragraph 1.9 (Program execution), states in point 8, among the least requirements for a conforming implementation, that:

access to volatile objects are evaluated strictly according to the rules of the abstract machine.

In other words, though the program should render the same results as demonstrated by the model described in the standard, only volatile are garanteed to be observed exactly as the standard describes it. Non volatile storage may well not be observed in a consistent manner (if you've already used a debugger on optimized code, you can clearly witness odd patterns in memory content updates with regard to what the program source actually specify). Another important point is that new operators are overloadable, meaning that the default behaviour described in the standard may be somewhat overriden. If a minimally conformant implementation of the standard (ie, one only enforcing volatile variable observation) runs a program where new has been overriden and does not rely on volatile data to keep track of its memory heaps, with optimization and strong inlining, the values of returned pointers may not be immediately visible in the variables storing them. If optimization passes determined that the variable lifetime could be shortened from what the program describes, it is also possible that the memory location corresponding to that variable may be repurposed and its content changed and observed in a debugger as such, though the program did not indicate such update. That is however the compiler's job to make sure that the program's execution fits the expected behaviour: from the program perspective, the variable will hold its value during its whole lifetime, and will not change unless the program specifies it by an update in any way allowed by the memory model.

In your example, if you access the variable p several times after the new assignment in your program, you won't notice a change of the value it contains since that assignment, the standard requires it. If you try to observe the memory location of that variable through some external device, you step out of the standard's abstract memory model, and could potentially witness changes in its content.

(1) using revision N3485 as reference, the paragraph numbering may have changed in later revisions.

didierc
  • 14,572
  • 3
  • 32
  • 52
0

The value of p is just a memory location. It will not change after it is assigned. The memory it is pointing to can change. It won't be changed by the OS. It can be changed by your program. If you simply allocate an array of integers (for example), and assign values to each integer. You can rest assured that those values will not change unless you explicitly overwrite them (or have a bug that does so.)

Brandon Kohn
  • 1,612
  • 8
  • 18
0

The address of a heap allocation will remain constant, variables don't change their values without your influence. Your p will even keep its value after delete, but if you try to access it you will trigger (hopefully) a segmentation fault. The value of N does not play a role.

Chiel
  • 6,006
  • 2
  • 32
  • 57