I agree with Ed, that the “Leaks” instrument is not as illuminating as the “Allocation” instrument. The “Leaks” instrument is most useful (in those edge-cases) where you are writing code that does manual alloc/free or retain/release. If not, it is generally identifying (usually very small) issues largely outside of your control. But if you don’t have your own code that is doing alloc/free or retain/release, the “Leaks” instrument is not terribly illuminating.
Your “Debug Memory Graph” diagnostics, though, are very effective in identifying strong reference cycles. But rather than focusing on the bottom of the tree (the fact that the NSSet
was used deeply within Foundation types), I would focus on the top of that tree. E.g., it looks like the NSSet
was created by some AVFoundation layer view. So, I would focus on the AVFoundation usage within the app.
Even better, in the left panel of the “Debug Memory Graph”, I would advise that we focus on our own objects, i.e., those objects over which we have control. To the right of the filter bar at the bottom of the panel on the left, there is a button that says “Show only content from workspace”: That’s a great way to focus on those objects over which you have control. See if there are any of your objects present that are still present that should no longer be there. E.g., you might have a view controller that shouldn’t be there (perhaps because of some strong reference cycle); and that view controller may lead to many objects (like this NSSet
) not being released, as well. So rather than worrying about the NSSet
, focus on the view controller (or which ever of your objects that should no longer be in memory). Bottom line, even though this big object was buried in some Foundation type, it often is a side-effect of some issue in the memory management of our own objects.
So, I might advise a “top down” focus on the objects in memory, rather than “bottom up”. A single top level object from your workspace that hasn’t been released will lead to a cacophony of lower-level objects, and there’s no reason to dwell on those lower-level objects until you’ve resolved your top-level objects that haven’t been released.
One last suggestion: When using “Debug Memory Graph”, sometimes it is not enough to know which type of object is keeping a strong reference to another, but rather you want help knowing where in your code these strong references are established. If you haven’t already, I would go to your scheme’s “Run” » “Diagnostics” options, and temporarily turn on “Malloc Stack Logging”. This way, when looking at the “Debug Memory Graph”, you can show the stack trace on the right, and it can help you navigate to the line of code that established a strong reference. Sometimes this isn’t necessary (as one can make educated guesses), but sometimes it can be incredibly useful if you cannot otherwise divine what you may have done to establish a strong reference cycle, or the like. Just remember to turn off this “Malloc Stack Logging” once you have identified and resolved your memory management issue.