Best way to proceed destroying ValueTree that points to owning ReferenceCountedObject

Hi all,

I’ve got an issue with my app, I constantly fall into the same issues with either ReferenceCountedObjects having leftover references, or leaks because of the ReferenceCountedObjects not being deleted.

This is mainly because I have structured objects in my app through a ValueTree, where the MainComponent creates the topmost component of the app, which has the topmost ValueTree in the structure. Then, when other components are added, they themselves have ValueTrees which are children of the topmost one - and each ValueTree in the system has a property which is a pointer to the component. This pointer is the source of my issues. The components are ReferenceCountedObjects so that the pointer can be a ValueTree property.

In the destructor of my object, I try and remove the object property before the actual destructor takes place. If I don’t, then there will be a leftover reference, in the tree, pointing to the object whose destructor has just been called.

(And the problem with that is..)

Even if the tree is destroyed with the object, the ReferenceCountedObject pointer inside the actual tree is removed after the object’s pointer is made useless - which means that the decReferenceCount() method inside the actual juce_ReferenceCountedObject implementation tries to decrement a nullptr, throwing a SegFault. (Should I let this pass?)

Therefore I chose to take an alternative route. In the destructor, I call removeAllProperties() on my ValueTree, but since this would decrease the referenceCount to 0, I use the unholy incReferenceCount() and decReferenceCountWithoutDeleting() directly before and after.

All this mess seemed to work well, but I often end up with new problems when restructuring or adding in extra systems. I feel like I’m not taking the best route. Does anyone have tips on how I could structure this better?

This sounds like the typical circular dependency problem with shared pointers. You could manage it manually something like how you suggest. But a better solution would be to break the circular dependency by using a weak reference: WeakReference. The only slight problem is that you’ll need to wrap the WeakReference to your master object also within another ReferenceCountedObject to store it in a var but that should then correctly release all the objects cleanly on tear-down.

1 Like

Thanks, I’ll try this solution out! I’m not familiar with weak pointers so they could probably help as you say.

WeakReference is definitely the way to go. Remember that Components have this functionality built in using the SafePointer term, so all you need to do is put using MySafePtr = Component::SafePointer<MyComponent> at the top, then use MySafePtr anywhere you like.

Remember that WeakReferences become null automatically if the referee is deleted, so you’ll probably want to check for that using if (mySafePtr != nullptr) or jassert(nullptr). Depending on your use case, you could build this into the wrapper that @martinrobinson-2 was suggesting, so you only have to do it once.

1 Like