3

I know that there is weak_ptr to break the cycle, but that is a fix, after the problem is discovered. Is there a pattern or tool that can be used to either detect or avoid cyclic referencing?

Tamás Szelei
  • 23,169
  • 18
  • 105
  • 180

4 Answers4

6

You avoid this by design. As Stephan T. Lavavej pointed out so nicely at the GoingNative2012 conference (you can check out the videos online), "ownership" is a directed acyclic graph, a DAG. There are no cycles in a DAG. If your ownership graph is not a DAG, your design is … questionable because A owning B and B owning A makes no sense. But shared_ptr is a "shared ownership pointer". The object or scope holding such a pointer owns the pointee. Try to think in terms of ownership graphs.

shared_ptr is not the right tool for every case. It's not supposed to allow you to code just like you'd do it in, say, Java where you don't have to think about ownership (much). It's supposed to provide automatic and deterministic cleanup. If you need a "non-owning" pointer, weak_ptr or a raw pointer is appropriate. Just make sure that the object a raw pointer points to stays alive long enough.

sellibitze
  • 27,611
  • 3
  • 75
  • 95
  • Java still does not have deterministic object destruction. Java does support a construct like C# using(){} construct, but this is far from the determinism C++ object destruction provides. – Unknown1987 Feb 23 '12 at 23:29
  • I did not claim that Java does have deterministic object destruction. – sellibitze Feb 24 '12 at 11:12
2

The obvious answer is not to use shared_ptr to objects which themselves might contain a shared_ptr. shared_ptr is somewhat special, and should be used sparingly.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
1

I would strongly echo what sellibitze said and rethink the design. If what you really have is a one way ownership and simply observing in the opposite direction consider weak_ptr. This allows you to check if an object is alive, but does not keep the object alive simply because you have a pointer to it.

Unknown1987
  • 1,671
  • 13
  • 30
  • I don't have a design to rethink. I want to know how to design so I don't have this problem. – Tamás Szelei Feb 23 '12 at 19:23
  • 3
    Without further context it is impossible to recommend how to structure the relationships. I would think about the problem in terms of who owns whom. If the model you end up with is a spaghetti mess of pointers too difficult to keep ownerships clearly defined, obviously that is not a well designed module. Break the problem into smaller chunks so that it can be encapsulated. This way you can build ownership hierarchies that are simple enough. – Unknown1987 Feb 23 '12 at 23:25
0

You can implement one, something like a wrapper over smart_ptr which on creation stores this pointer (e.g. by macro). Then build directed graph with edges from stored this to object contained by shared_ptr and detect any cycles, e.g. by topological sorting.

I would recommend this only for large code base with intensive shared_ptr usage and inability to control all design aspects. For other cases just use @sellibitze recommendation.

Andriy Tylychko
  • 15,967
  • 6
  • 64
  • 112