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);
}
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With