user -1
user -1

Reputation: 110

Array of pointers unexplained behavior (with shallow copy) c++

This is a behavior with array of pointers in C++ (GNU GCC compiler) that I can't find an explanation for, hopefully someone can clear the confusion.

I'm creating an array of pointers (arr_ptr), The pointers are pointing to valid data, then I create another array of pointers (arrcopy), I do -what I think- a shallow copy (arrcopy = arr_ptr), and I get the data as expected...so far so good.

The part I am not understanding is, after I delete arr_ptr, shouldn't arrcopy still be pointing to my valid data? Why this is not happening? Thank you.

int main()
{
    int a = 1; int b=2; int c=3;
    int* ap = &a; int* bp = &b; int* cp = &c;

    // Array of pointers
    int** arr_ptr = new int*[3];
    arr_ptr[0] = ap;
    arr_ptr[1] = bp;
    arr_ptr[2] = cp;

    //shallow copy
    int** arrcopy = arr_ptr;

    cout << "Values: " << *(arr_ptr[0]) << " " << *(arrcopy[0]) << endl;
    cout << "Addresses: " << arr_ptr[0] << " " << arrcopy[0] << endl;
    cout << endl;

    a++;

    cout << "After Incrementing a:" << endl;
    cout << *(arr_ptr[0]) << " " << *(arrcopy[0]) << endl;
    cout << arr_ptr[0] << " " << arrcopy[0] << endl;
    cout << endl;

    *(arr_ptr[0]) = 5;

    cout << "After updating a value to 5:" << endl;
    cout << *(arr_ptr[0]) << " " << *(arrcopy[0]) << endl;
    cout << arr_ptr[0] << " " << arrcopy[0] << endl;
    cout << endl;

    //so far so good - works as expected

    //deleting arr_ptr
    delete[] arr_ptr;

    // Why?: shouldn't arrcopy still be pointing to A
    cout << "Values: " << *(arr_ptr[0]) << " " << *(arrcopy[0]) << endl; //The result I am expecting here is: unknown_value  5
    cout << "Addresses: " << arr_ptr[0] << " " << arrcopy[0];
    cout << endl;


    return 0;
}

arr_ptr Initialization

After Shallow copy of arr_ptr to arrcopy (arrcopy = arr_ptr) enter image description here

After deleting arr_ptr, shouldn't arrcopy still be pointing to the memory locations of a,b,c data values?! enter image description here

Upvotes: 2

Views: 631

Answers (2)

Leon
Leon

Reputation: 32504

Neither arr_ptr nor arrcopy is an array. Both are just pointers.

A C++ pointer is a little overloaded. It can point to a single object or to an array of objects.

In your case arr_ptr is initialized with the address of the array that you allocated in the dynamic memory. But it could as well be initialized with an address of a single object on the stack:

int i = 0;
int** arr_ptr = &i;

By copying the value of that pointer into another pointer of the same type you simply have two pointers referring to the same memory location:

              // array in the heap
              [xxxxxxxxxxxxxxxxxxxxxxx]
              ^
             / \
            /   \
           /     \
       arr_ptr  arrcopy

Upvotes: 2

Galik
Galik

Reputation: 48635

You do not have 2 arrays after the assignment you have 2 pointers to the same array:

arr_ptr -------->|ptr0|ptr1|ptr2|ptr3... (allocated memory)


arr_cpy = arr_ptr; // copy only the pointer

Now both pointers point to the same allocated memory:

arr_ptr -------->|ptr0|ptr1|ptr2|ptr3...
                   ^
arr_cpy -----------|


delete[] arr_ptr; // invalidate the memory that both pointers point to

This gives:

arr_ptr -------->|xxx0|xxx1|xxx2|xxx3... (invalid memory)
                   ^
arr_cpy -----------|

It doesn't matter which pointer you call delete[] on, they both point to the same block of allocated memory so after the call they both point to the same block of invalidated memory.

What you need to do is copy the whole array:

int** arr_cpy = new int*[3];
std::copy(arr_ptr, arr_ptr + 3, arr_cpy); // copy the pointers to the new array

Or much better use a std::vector:

int main()
{
    int a = 1; int b=2; int c=3;
    int* ap = &a; int* bp = &b; int* cp = &c;

    // Array of pointers
    std::vector<int*> arr_ptr{3};
    arr_ptr[0] = ap;
    arr_ptr[1] = bp;
    arr_ptr[2] = cp;

    //shallow copy
    std::vector<int*> arr_cpy = arr_ptr; // copy the whole vector

    // ... etc.

No need for delete[], memory is deallocated automatically when your vector goes out of scope.

Upvotes: 3

Related Questions