Avoid indirect circular references when using shared_ptr and weak_ptr

I am currently building an application that relies heavily on shared_ptr , and everything looks good so far - I did my homework and you have a good idea about some problems using shared_ptr s.

One of the most known problems with shared_ptr is circular dependency - these problems can be solved by storing weak_ptr , which do not affect the lifetime of objects in the chain. However, I struggle to get my head when I need to store a pointer to an external object using weak_ptr - . I am not sure if it is forbidden, not recommended or safe .

The following diagram describes what I mean (black arrows indicate shared_ptr , dotted lines indicate weak_ptr ):

alt text http://img694.imageshack.us/img694/6628/sharedweakptr.png

  • The parent contains shared_ptr for two children, both of which access the parent using weak_ptr .
  • In the constructor of the first child, I get through the parent weak_ptr pointer to the second child element and save it locally.

The code is as follows:

 #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> #include <boost/make_shared.hpp> #include <boost/enable_shared_from_this.hpp> class child; class child2; class parent; class parent : public boost::enable_shared_from_this<parent> { public: void createChildren() { _child2 = boost::make_shared<child2>(shared_from_this()); _child = boost::make_shared<child>(shared_from_this()); } boost::shared_ptr<child> _child; boost::shared_ptr<child2> _child2; }; class child { public: child(boost::weak_ptr<parent> p) { _parent = p; _child2 = boost::shared_ptr<parent>(p)->_child2; // is this safe? } boost::weak_ptr<parent> _parent; boost::shared_ptr<child2> _child2; }; class child2 { public: child2(boost::weak_ptr<parent> p) { this->_parent = p; } boost::weak_ptr<parent> _parent; }; int main() { boost::shared_ptr<parent> master(boost::make_shared<parent>()); master->createChildren(); } 

I tested this and it seems to be working fine (I have no memory leak messages), however my question is: Is it safe? And if not, why not?

+7
c ++ boost shared-ptr weak-ptr
source share
3 answers

The child constructor looks safe, as you call it. However, it is unsafe at all.

The problem is passing in weak_ptr as an argument in the child constructor. This means that you need to worry about whether the weak pointer is for an object that no longer exists. Changing this parameter to shared_ptrs and converting to weak_ptr during storage, we know that the object still exists. Here's the change:

 child(boost::shared_ptr<parent> p) { _parent = p; _child2 = p->_child2; // This is this safe } 
+6
source share

One of the most known problems with shared_ptr is circular dependencies - these problems can be solved by storing weak_ptrs, which does not affect the lifetime of objects in the chain.

Wrong. This cyclic dependency exists or does not work.

If the problem exists, then a weak link is simply not an option.

where you need to save a pointer to an external object via weak_ptr

weak_ptr almost never required.

There are several specific cases where weak_ptr is suitable, but basically it is part of the shared_ptr cult: instead of accidentally throwing shared_ptr for problems, they randomly throw half shared_ptr and half weak_ptr (as seen on SO).

+3
source share

You will get a bad_weak_ptr exception if "p" was (somehow) destroyed already. Thus, it is safe that the child ctor expects exceptions and is not safe otherwise.

0
source share