Does Xcode Memory graph offer any smart visual indicators for strong references that aren't memory cycles?
Asked Answered
R

1

3

As a follow up to my previous How can I create a reference cycle using dispatchQueues?:

For the strong references (that create leaks, but aren't reference cycles) e.g. Timer, DispatchSourceTimer, DispatchWorkItem, the memory graph doesn't create a purple icon, I suspect it's simply because it doesn't find two objects pointing back to each other strongly.

I know I can go back and forth and observe that a specific class is just not leaving the memory, but wondering if Xcode is providing anything more.

  • Is there any other indicator?
  • I know Xcode visually shows the number of instances of a type in memory. But is there a way to filter objects that have more than 3 instances in memory?
Rowles answered 22/5, 2019 at 17:14 Comment(4)
“return to point that object in question should be have been deallocated”. I agree with that mindset, I can do that per flow, but I want to just open the memory graph and just use my app for like 10 minutes like I normally do, then see its memory graphs.Rowles
Stating the obvious: The difference between memory cycles and strong references is that memory cycles have a purple icon :D. I can use the app and go through 20 different flows and then see its backtrace. Maybe this would seem a bad approach at first, but if you have resolved your memory cycle issues per every release, then over time you have only 2-3 leaks and then going through the entire app and quickly filtering or looking for visual signs will make it faster. But there seems not to be an indicator. Thank you RobRowles
“that create leaks” ... Technically these are not leaks (which is why “Leaks” tool can’t find them either). This is “abandoned” memory for which there is a reference to it, but your code doesn’t have any reference to it anymore. Leaked memory is memory that can’t be referenced again and there is no reference to it (e.g. a malloc without a free).Undress
See developer.apple.com/videos/play/wwdc2012/242/?time=1798Undress
U
2

You ask:

For the strong references (that create leaks, but aren't reference cycles) e.g. Timer, DispatchSourceTimer, DispatchWorkItem, the memory graph doesn't create a purple icon, I suspect it's simply because it doesn't find two objects pointing back to each other strongly.

Yes. Or more accurately, the strong reference cycle warning is produced when there are two (or more objects) whose only strong references are between each other.

But in the case of repeating timers, notification center observers, GCD sources, etc., these are not, strictly speaking, strong reference cycles. The issue is that the owner (the object that is keeping a strong reference to our app’s object) is just some persistent object that won’t get released while our app is running. Sure, our object might still be “abandoned memory” from our perspective, but it’s not a cycle.

By way of example, consider repeating timer that is keeping strong reference to our object. The main runloop is keeping strong reference to that timer and won’t release it until the timer is invalidated. There’s no strong reference cycle, in the narrow sense of the term, as our app doesn’t have strong reference back to the runloop or the timer. But nonetheless, the repeating timer will keep a strong reference to our object (unless we used [weak self] pattern or what have you).

It would be lovely if the “Debug Memory Graph” knew about these well-known persistent objects (like main runloop, default notification center, libDispatch, etc.), and perhaps drew our attention to those cases where one of these persistent objects were the last remaining strong reference to one of our objects. But it doesn’t, at least at this point.

This is why we employ the technique of “return to point that most of my custom objects should be have been deallocated” and then “use ‘debug memory graph’ to identify what wasn’t released and see what strong references are persisting”. Sure, it would be nice if Xcode could draw our attention to these automatically, but it doesn’t.

But if our app has some quiescent state, where we know the limited types of objects that should still be around, this “debug memory graph” feature is still extremely useful, even in the absence of some indicator like the strong reference cycle warning.

I know I can go back and forth and observe that a specific class is just not leaving the memory, but wondering if Xcode is providing anything more.

  • Is there any other indicator?

No, not that I know of.

  • I know Xcode visually shows the number of instances of a type in memory. But is there a way to filter objects that have more than 3 instances in memory?

Again, no, not that I know of.

Undress answered 22/5, 2019 at 18:17 Comment(5)
FWIW, I didn't say they are cycles. As for notificationCenter, is it required? Do you just mean for this scenario:Rowles
I didn’t mean to suggest that you said they were cycles. But many people do use the term loosely, so I wanted to be precise in my terminology. Re notification center question you reference, that’s really about whether you need to remove the observer. I’m talking about the need to make sure that your notification center observation closure doesn’t establish a strong reference to self, which is a completely different issue.Undress
I was among the many people until these questions. You said: "I’m talking about the need to make sure that your notification center observation closure doesn’t establish a strong reference to self" That would be a reference cycle then right? You're not talking about the need of doing something like: center.removeObserver(self.localeChangeObserver) (mentioned here)Rowles
Again, just like the Timer example, it’s not technically a “strong reference cycle”. When you look at the memory graph, you’re not going to see those circular references of a true cycle. It’s just that the Notification Center, which never is deallocated while the app is running, will keep a reference to any reference types captured by the observer closure (unless you weakly capture them) until the observer is removed.Undress
I think I got it. ThanksRowles

© 2022 - 2024 — McMap. All rights reserved.