Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why did this assignment of a shared pointer have no effect after returning from nested function?

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?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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.

>Solution :

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;
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading