c++pointerslanguage-lawyernew-operatorundefined-behavior

Is difference between two pointers pointing to the same deallocated array well-defined in C++?


int main() {
    const int length = 10000;
    double *A = new double[length];
    double *first = A;
    double *last = A + length - 1;
    delete[] A;
    ptrdiff_t diff = last - first;
}

In C++, is it well-defined to take the difference of two pointers pointing to some locations in the same array after it has been deallocated?

The reason I am asking this is because I have an array of pointers pointing to the same buffer. The array gets reallocated, and I need to update the pointers. I do this by computing the difference between pointer n and pointer 0 in the pointer array after the buffer is reallocated. (Of course I can compute the differences before reallocation and store it, but I am a bit curious.)


The same question was asked for the C language here and the behavior seems undefined in C. Is it also undefined in C++?


Solution

  • The result is also undefined in C++. According to [expr.add]/5:

    When two pointer expressions P and Q are subtracted, the type of the result is an implementation-defined signed integral type; this type shall be the same type that is defined as std::ptrdiff_t in the header (17.2.4).

    • If P and Q both evaluate to null pointer values, the result is 0.
    • Otherwise, if P and Q point to, respectively, array elements i and j of the same array object x, the expression P - Q has the value i − j.
    • Otherwise, the behavior is undefined. [Note: If the value i − j is not in the range of representable values of type std::ptrdiff_t, the behavior is undefined. — end note]

    I suppose if you want to get really technical, it's barely possible that by the time you try to do last - first, some other thread could have done an allocation, so that last and first did happen to point into an array again, in which case there's room for argument that the result might be defined (but I'm pretty sure it's not intended to be, and it's essentially impossible to predict when it would or wouldn't be--but I suppose if we want to be complete, the possibility does exist).