Alonbs
Alonbs

Reputation: 259

Uninitialized value when dealing with shared_ptr

I'm sure this is very simple, but I'm rather new to smart pointers, and I couldn't find an answer to this.

Scenario is very simple: I have a class A, that holds a shared_ptr to some object X:

class A{
    shared_ptr<const X> _asX;
}

now after a series of function calls, I'm creating a new object of type B, that also holds this X. something like:

class B {
private:
    shared_ptr<const X> _bsX;
public:
    B(): _bsX(nullptr) // - maybe this is problematic {}
    foo(shared_ptr<const X>& x)
    {
        _bsX = x;
        // The line above gives me undefined behavior, 
        // and when I run valgrind I get "Conditional jump or move
        // depends on uninitialized value(s)",
        // telling me this is not the correct way to do things. 
    }

Note that it is deliberate the foo really sets the value of _bsX and not the constructor.

So as stated above - depending on the compiler, I something get segmentation faults - which usually means some value was not initialized, and later confirmed by valgrind.

So what should I do - I've tried using 'reset' etc. but I got so confused I'm asking for your help. Could it be the const ? or the pass by reference ? or the '=' operator.

And while we're at it - should I be passing X with its wrapper (the shared_ptr) to foo, or should I pass the raw pointer, and then make it shared ? if so - could you please give an example. I tried that as well, and got errors.

Upvotes: 0

Views: 1209

Answers (1)

Alonbs
Alonbs

Reputation: 259

Ok, I found the problem, and it's no related to smart pointers at all, but since I'm new to this - I thought it might be. I'll leave this answer for future references. This is what I did (simplified):

class A{

private:

    shared_ptr<const int> _num;

public:
    A()
    {
        _num = make_shared<const int>(5);
    }

    const shared_ptr<const int>& getNum() const {return _num; }

    void printNum()
    {
        cout << *_num.get() << endl;
    }
};

class B
{


public:

    struct C{
        C() : _num(nullptr){}
        void boo(shared_ptr<const int> & num) { _num = num;}
        shared_ptr<const int> _num;
    };

    B() {}

    void foo(shared_ptr<const int>& num)
    {
        cs.reserve(2);
        for (uint32_t i = 0; i < 2 ; ++i) {

            cs.push_back(C()); // This was missing.
            cs[i].boo(num);
        }
    }

    void printCNum()
    {
        for (C c : cs) {
            cout << *c._num.get() << endl;
        }
    }

private:

    vector<C> cs;
};


int main()
{
    A a{};
    shared_ptr<const int> xx = a.getNum();

    B b{};
    b.foo(xx);

    a.printNum();
    b.printCNum();

}

Silly me, I thought that when you reserve a vector of Objects (not pointers/references) it also calls their constructor. It turn out it's not. Specifically, I increased the capacity of the vector, but not its size.

Upvotes: 1

Related Questions