Home > Software design >  Substituting a reserved value dynamically doesn't work
Substituting a reserved value dynamically doesn't work

Time:11-29

I am trying to copy one dynamically reserved array into another, both of which are placed in a vector. But it does not work. Why?

struct A {
    int *p;
};

int main()
{
    vector<A> v;
    A test;
    test.p = new int[5];

    //fill the array
    for (int i = 0; i < 5; i  )
        test.p[i] = i;

    v.push_back(test);

    A test2;
    test2.p = new int[10];

    //fill the array
    for (int i = 0; i < 10; i  )
        test2.p[i] = i;

    delete[] test.p;
    //reallocate test to test2
    test.p = new int[10];
    //copy test2 to test
    for (int i = 0; i < 10; i  )
        test.p[i] = test2.p[i];
    
    //delete test2
    delete[] test2.p;

    //print the array
    for (int i = 0; i < 10; i  )
        cout << v[0].p[i] << endl;

    return 0;
}

My output is:

0
0
-997294064
32767
4
0
33
0
-997220688
32767

CodePudding user response:

The only thing in A is a pointer. When you push a copy of test to the vector, notice that the copied version in the vector will have a pointer pointing to the same location as the one that's not in the vector.

So later, when you delete the data from the outside copy, you are also deleting the data from the one in the vector, because both of them are pointing to the same data.


Next part, you reallocated more memory for test through new int[10]. So now test.p is pointing to another memory location. However, this does not have any effect to the copy in the vector, because the one in the vector is still pointing to the old location. You can only change where it is pointing at manually.

Because of that, the one in the vector lost its 5 original data, and was never updated with the 10 new data.


To make it work, you can reassign the pointer in the vector manually to the one outside the vector after you have allocated the new memory for the outside one:

v[0].p = test.p;

CodePudding user response:

The problem can be simplified quite a bit

A test;
test.p = new int[5]{};

A test_copy = test; // vector::push_back creates a copy as well

delete[] test.p; // deletes where test.p and test_copy.p point

test.p = new int[10]{}; // test_copy.p is still pointing at the deleted address

for (int i = 0; i < 10; i  ) {
    // test.p is valid, but test_copy.p is not.
    // use-after-free
    std::cout << test_copy.p[i] << '\n';
}

live link

When you push test into the vector, you are creating a (shallow) copy of it. When you delete test.p you're deleting the memory that the copy is pointing to as well, but when you later assign to test.p, it doesn't update the copy's p pointer.

  • Related