Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

shared_ptr - why does it break?

Tags:

c++

shared-ptr

While developing a tree-like data structure, I wrote something like this:

    #include <memory>

    class Node: public std::enable_shared_from_this<Node> {
    public:

        void set_root(Node & n);
    private:
        std::shared_ptr<Node> root;
        std::shared_ptr<Node> leaf;
    };

    void Node::set_root(Node & n) {
        root = n.shared_from_this();
        n.leaf = shared_from_this();
    }

    int main() {
        Node n1, n2;
        n1.set_root(n2);
    }

The code compiles with clang but breaks run-time ("libc++abi.dylib: terminating with uncaught exception of type std::__1::bad_weak_ptr: bad_weak_ptr") Why?

EDIT So based on the answers, I came up with the version that seems to be working:

    #include <memory>

    class Node;
    typedef std::shared_ptr<Node> Node_SP;

    class Node: public std::enable_shared_from_this<Node> {
    public:

        void set_root(Node & n);
    private:
        std::shared_ptr<Node> root;
        std::shared_ptr<Node> leaf;
    };

    void Node::set_root(Node & n) {
        root = n.shared_from_this();
        n.leaf = shared_from_this();
    }

    int main() {
        Node_SP n1 = std::shared_ptr<Node>(new Node);
        Node_SP n2 = std::shared_ptr<Node>(new Node);

        n1->set_root(*n2);
    }
like image 313
tnorgd Avatar asked Dec 02 '25 08:12

tnorgd


2 Answers

To do it's job, enable_shared_from_this<Node> has to store a weak_ptr<Node> to itself. This weak_ptr is default-constructed to be null. When a shared_ptr is constructed to take over ownership of an object, either vía make_shared or by passing a raw pointer, it sets said weak_ptr to refer to that new shared_ptr. If you then call shared_from_this() on the object, the weak_ptr gets locked and another shared_ptr can be returned.

However, in your case there is no shared_ptr holding n1 and n2, so when calling shared_from_this() the lock gets executed on the null weak_ptr, resulting in said exception.

Long story short: don't call shared_from_this() on a object that is not owned by a shared_ptr - especially not on stack based objects like in your example.

like image 119
Arne Mertz Avatar answered Dec 04 '25 22:12

Arne Mertz


shared_ptr assumes the object is allocated on the heap, but you've allocated it on the stack.

Use new instead and let shared_ptr call delete for you.

like image 45
user541686 Avatar answered Dec 04 '25 22:12

user541686



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!