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';
}
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.