Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Properties of a pointer to a zero length array

Consider

int main()
{
    auto a = new int[0];
    delete[] a; // So there's no memory leak
}

Between the copy initialisation and deletion, are you allowed to read the pointer at a + 1?

Furthermore, does the language permit the compiler to set a to nullptr?

like image 936
Bathsheba Avatar asked Feb 27 '20 21:02

Bathsheba


People also ask

What is a zero-length array?

Zero-length arrays, also known as flexible arrays, are used to implement variable-length arrays, primarily in structures. That's a little confusing, so let's look at an example. Say you wanted a structure to represent an email: Yes, we're missing a lot of fields. This is just an example; bear with me.

What is the size of a pointer to an array?

The pointer ptr, and all pointers, are 8 bytes, because they hold addresses, which are 8 bytes, or 64 bits. Assigning any address to an array variable is not allowed.

Can you have an array with size 0?

Although the size of a zero-length array is zero, an array member of this kind may increase the size of the enclosing type as a result of tail padding. The offset of a zero-length array member from the beginning of the enclosing structure is the same as the offset of an array with one or more elements of the same type.


2 Answers

Per recent CWG reflector discussion as a result of editorial issue 3178, new int[0] produces what is currently called a "past-the-end" pointer value.

It follows that a cannot be null, and a + 1 is undefined by [expr.add]/4.

like image 194
T.C. Avatar answered Oct 21 '22 19:10

T.C.


    auto a = new int[0];

According to [basic.compound.3], the value stored in a must be one of the following:

  1. A pointer to an object (of type int)
  2. A pointer past the end of an object
  3. Null
  4. Invalid

We can rule out the first possibility since there were no objects of type int constructed. The third possibility is ruled out since C++ requires a non-null pointer to be returned (see [basic.stc.dynamic.allocation.2]). Thus we are left with two possibilities: a pointer past the end of an object or an invalid pointer.

I would be inclined to view a as a past-the-end pointer, but I don't have a reputable reference to definitively establish that. (There is, though, a strong implication of this in [basic.stc], seeing how you can delete this pointer.) So I'll entertain both possibilities in this answer.

Between the copy initialisation and deletion, are you allowed to read the pointer at a + 1?

The behavior is undefined, as dictated by [expr.add.4], regardless of which possibility from above applies.

If a is a past-the-end pointer, then it is considered to point to the hypothetical element at index 0 of an array with no elements. Adding the integer j to a is defined only when 0≤0+j≤n, where n is the size of the array. In our case, n is zero, so the sum a+j is defined only when j is 0. In particular, adding 1 is undefined.

If a is invalid, then we cleanly fall into "Otherwise, the behavior is undefined." (Not surprisingly, the cases that are defined cover only valid pointer values.)

Furthermore, does the language permit the compiler to set a to nullptr?

No. From the above-mentioned [basic.stc.dynamic.allocation.2]: "If the request succeeds, the value returned by a replaceable allocation function is a non-null pointer value". There is also a footnote calling out that C++ (but not C) requires a non-null pointer in response to a zero request.

like image 26
JaMiT Avatar answered Oct 21 '22 17:10

JaMiT