Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is object storage allowed to be implicitly or explicitly reused if lifetime ended?

Consider the following example:

// create some storage
alignas(int) char buffer[2 * sizeof(int)];

// new object of type int at the storage of buffer, the int pointed
// to by p begins its lifetime here, buffer's lifetime is over
int* p = new (buffer) int{42};

// some entirely unrelated int
int j = 17;

Is it allowable for the other storage at the end of buffer, the part that isn't already used by the new int object pointed to by p, to be reopened to the stack and implicitly reused by subsequent objects of automatic storage duration? In other words, is a conforming implementation allowed to have &j == p+1?


Relatedly, would explicitly reusing the other storage be well-defined behavior?

alignas(int) char buffer[2 * sizeof(int)];
int* p = new (buffer) int{42};
int* q = new (p+1) int{6}; 

That is, are both ints pointed to by p and q still within their lifetimes?

like image 685
Barry Avatar asked Sep 12 '16 16:09

Barry


People also ask

What is the lifetime of an object and how can you extend the lifetime of an object?

The lifetime of a temporary object may be extended by binding to a const lvalue reference or to an rvalue reference (since C++11), see reference initialization for details.

What is the lifetime of an object in c++?

C/C++ use lexical scoping. The lifetime of a variable or object is the time period in which the variable/object has valid memory. Lifetime is also called "allocation method" or "storage duration."


1 Answers

The compiler does not have to use unique areas of memory for each variable in a stack, and as long as it can determine, that the program can not measure the re-use - e.g. checking whether the two variables have the same address, would possibly cause the compiler to ensure they didn't share memory.

Example

int a;
// do some stuff with a.

int b; 
// do some stuff with b.

Assuming that both a and b use stack, they may share the address as the compiler can tell their distinct usage.

Creating an item on the stack is a simple instruction

sub stackPointer, #AmountOfSpaceNeeded

In this example, the amount of space does not affect the speed of allocation.

Creating an item on the heap requires finding some unused area of memory, or "mapping" some new address space in, and takes many times the cost of the one (or two with a frame pointer) instructions for using the heap.

It may also create false-positives on memory checkers, where there is a disagreement about the usable amount of spare memory in an object.

So there is little value in the optimization of using a location in the heap, to save storage on the stack, as

  1. Not all functions use the heap
  2. There is no time saving in using just the heap
  3. The code mechanisms behind the heap may perform measurement (buffer-overrun detection), which results in the compiler breaking the as-if rule.
  4. As well as determining that the space is unused, the compiler would also need to determine that the life of the memory was correct, as heap objects can be destroyed before a function/block of code finishes.
like image 199
mksteve Avatar answered Oct 20 '22 19:10

mksteve