.svg: addAndMakeVisible(): Am I leaking?

svg

#1

Hi,
my AudioProcessorEditor uses an .svg; when addAndMakeVisible() the entire .svg it seems to work fine (abstraction):

class editor:
	public juce::AudioProcessorEditor {
	juce::ScopedPointer<juce::Drawable>svg= juce::Drawable::createFromSVG(
		*juce::ScopedPointer<juce::XmlElement>(
			juce::XmlDocument::parse (BinaryData::unrivaled_svg)));
public:
	editor () {
	    std::clog<<__FUNCTION__<<" "<<layout->getNumChildComponents()<<std::endl;
        addAndMakeVisible (svg);
	    setSize (svg->getWidth(), svg->getHeight());
    }
};

but when all elements (and in a simple test .svg there are only two simple sub elements) are added seperately a myriad of memory leaks is asserted at plugin close:

	editor () {
	    std::clog<<__FUNCTION__<<" "<<layout->getNumChildComponents()<<std::endl;
        for (auto component: svg->getChildren()) {
            std::clog<<__FUNCTION__<<" "<<component->getComponentID()<<std::endl;
            addAndMakeVisible (component);
        }
	    setSize (svg->getWidth(), svg->getHeight());
    }

whats the difference?


#2

A Component can only have one parent. So if you add a child of a drawable to another parent, it no longer belongs to the Drawable. So the Drawable will no longer be in charge of deleting it when it is itself destroyed.


#3

Thanks!


#4

…but then again, why doesn’t it transfer the ownership at addAndMakeVisible()?
Or in other words how do I correctly transfer the ownership?


#5

If you’re going to remove it from its Drawable parent, then it becomes your responsibility to delete it when you’re done.


#6

But I don’t understand, why when the Drawable is parent it holds the ownership, while when the component to which the element is added with addAndMakeVisible becomes the parent it does not become the owner…
If I understand that correctly this isn’t very intuitive nor stringent.


#7

It’s up to the author of a Component to decide how they manage ownership of their children - nothing in the base class attempts to do that for you. This is how the entire library works, it shouldn’t be a surprise!

In the case of DrawableComposite, it was designed to delete its children when you delete it. But if you remove its children then it’s up to you how you choose to manage their lifetimes.


#8

So, you are saying: there is no contradiction that the Component (that does not hold any ownership of its children itself) is able to remove the ownership that a DrawableComposite holds by becoming the new parent of the transferred child from that DrawableComposite.


#9

I don’t really understand the question… The “Component” doesn’t do anything here, you wrote the code which removes the child from its parent. Once you’ve done that, the DrawableComposite can’t be expected to still own it, it would be even more confusing if it continued to keep a pointer to something that it no longer contains.


#10

So, where do I remove the child from its parent then? addAndMakeVisible is a method of the Component.


#11

Like I said: they can only have one parent. So you removed them from their parent by using addAndMakeVisible to add them to something else!


#12

I don’t know if that answer @raketa’s question: I guess he may be asking instead how should he properly get rid of the Drawable extracted from the DrawableComposite, after he has transferred it to be a child of another Component.

In the specific case of the code that he showed, one of the following should be used:

  • Add a member variable of type OwnedArray <Component> to the editor class, then store there the pointers of each “children” component that you transfer from the Drawable to the editor. When the editor is destroyed, all the pointers stored in that array will be deleted too.

or

  • Simply call deleteAllChildren() in the editor's destructor. This is the quick-and-dirty solution, I prefer the first one as it is more elegant (I don’t like having to invoke explicit deletions) but you may perfectly fine with it.