Consider this mwe:
#include<iostream>
#include<memory>
#include<vector>
using namespace std;
struct A {
shared_ptr<vector<int>> b;
};
void foo(vector<A> &vec)
{
auto c = shared_ptr<vector<int>>(new vector<int>{42});
vec.back().b = c;
cout << "Foo size " << vec.back().b->size() << endl;
}
void bar(A &a)
{
auto vec = vector<A>{a};
foo(vec);
}
int main()
{
A a;
bar(a);
cout << "Main size" << a.b->size() << endl;
return 0;
}
This is the program's output:
~ ./a.out
Foo size 1
[1] 107400 segmentation fault (core dumped) ./a.out
Why does a.b->size() yield in a segfault, instead of asking the vector which contains 42 to report its size?
Background: I have only very superficial knowledge of C . Usually I program in Python but recently (some weeks ago) I started working on someone else's C code base and added some features to it.
CodePudding user response:
std::vector and other standard containers always store copies of objects.
When you do auto vec = vector<A>{a};, a is copied into the vector, so any changes to the vector don't affect a.
CodePudding user response:
In main(), a.b doesn't point at a valid vector, so accessing a.b->size() is undefined behavior.
bar() creates a new vector that holds a copy of the A object that was passed in to it. foo() is then acting on that copied A object, not the original A object in main().
If you want foo() to act on the original A object in main(), you will have to change bar() to pass a vector<A*> instead to foo(), eg:
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
struct A {
shared_ptr<vector<int>> b;
};
void foo(vector<A*> &vec)
{
auto c = shared_ptr<vector<int>>(new vector<int>{42});
vec.back()->b = c;
cout << "Foo size " << vec.back()->b->size() << endl;
}
void bar(A &a)
{
auto vec = vector<A*>{&a};
foo(vec);
}
int main()
{
A a;
bar(a);
cout << "Main size" << a.b->size() << endl;
return 0;
}
