Home > Mobile >  segmentation fault when acessing attribute of an smart pointer to class, inside another class
segmentation fault when acessing attribute of an smart pointer to class, inside another class

Time:02-24

i tried to make this:

#include <iostream>
#include <memory>

class B
{
    public:
    std::string var;
    
    B()
    {
        var = "original";
    }

    void print()
    {  
        std::cout << "composition " << std::endl;
    }
};

class A
{
    public:
    int a_attribute = 10;
    std::unique_ptr<B> b;

};

int main()
{
    A a;
    a.b->print();
}

That seems to work fine, except when i try to access the attributes of B, with e.g:

std::string test = a.b->var;

which leads to segmentation fault error

why i'm not getting an error to a.b->print(); but getting segfault to a.b->var; ?

CodePudding user response:

You problem is here, in A you have

std::unique_ptr<B> b;

this creates a smart pointer to a B object. But it there is no B object that it points at. Before you can use it you must create a B object and set 'b' to point at it.

I dont know exactly how and when you want to create your B but you can do this

A a;
a.b = std::make_unique<B>();
a.b->print();

this will create a new B using the default contructor and make 'a.b' point at it. This is more effiecient short hand for

A a;
B *b1 = new B;
a.b.reset(b1);
a.b->print();

which explicitly creates a B and then sets a.b to point at it.

Note that you do not have to free the B object. Thats the point of smart pointers they will do it for you.

You asked why some combinations work and some dont.

You had Undefined Behavior. This can do anyting , including worst of all, appearing to work. Then at midnight on Christmas eve your largest customer submits a huge order to your system and it crashes. Every professional dev has had some occurrence of this. Ways to avoid: crank up the compiler warning levels, never ignore warnings. Use a tool like valgrind or other commercial checker tools.

For me your original code as posted worked. Why, because the invoked method doesnt actually need any data in the B object. But If I change to this

void print()
{
    std::cout << "composition " << std::endl;
    std::cout << var << std::endl;
}

it fails because now we are referencing data in the B object, but there isn't one.

Note that on a different compiler your original code will not work

  • Related