Xcode memory tools disagree on presence of Zombie Objects - ios

My app seems to have a memory problem. I'm not getting any crashing, but when testing on device, both Instruments and the Debug Navigator agree that the amount of memory my app is using keeps increasing depending on what I'm doing in the app.
So, I tried to diagnose the problem.
First, I thought about normal memory leaks -- and there were many. So, after a lot of work with the Instruments -> Leaks template, I was able to eliminate them.
But the memory problem persisted.
So, I decided to look for zombie objects. First, I enabled zombies in Xcode. Because I was unsure whether I needed to enable zombies for "Run" or "Test" or both, I did both. So, that's Edit Scheme -> Run -> Diagnostics -> Zombie Objects and Edit Scheme -> Test -> Diagnostics -> Zombie Objects.
I was also unsure whether to run Instruments through a debug or release build configuration, so I tried it with both (with the same outcome).
Here's a screenshot showing the location of the Debug Navigator:
Here's a screenshot of the memory options I enabled prior to using View Memory Graph Hierarchy:
Now that zombies are enabled, I go to Debug Navigator -> View Memory Graph Hierarchy, and Xcode builds a memory graph that says my app has something like a thousand zombie objects. There are zombies of all kinds -- everything from SceneKit stuff to CloudKit and GameplayKit stuff.
Here's a screenshot of some of those zombie objects:
So, I decided to investigate further using Instruments.
Here's what Apple says on using Instruments to detect zombies:
"If a call is made to a deallocated object, a flag is inserted in the
timeline pane and a Zombie Messaged dialog appears, indicating that a
message was sent to a deallocated object at a specific memory
address."
However, if I open Instruments and use the Zombies template, I never see any such flags/dialogs.
Here's a screenshot showing what I see after running the Instruments Zombies template (notice the lack of flags/dialogs):
Question: Why might the memory graph hierarchy tool and Instruments disagree so markedly on the presence of zombies? Is there some further Xcode configuration I'm missing or something? How should I proceed?
Thanks!

Related

How can I debug iOS app freeze if the pause button does not provide any information?

I am facing app freezing issue that is not getting detected in exception breakpoints. All my UI related code runs on main thread. As suggested in the question My app freezes but no error appears, I tapped on the pause button to check error, but cannot figure out anything from it. Please help me understand better. Attaching the screenshot of my xcode screen here:
When your app freeze.. try the following and resolve it
In Xcode(8 or Higher)
Analyze Code - Command+Shift+B
Enable Address Sanitizier in Xcode
Memory Graph
Thread Sanitizer and Static Analysis
Xcode makes it easier to find several new categories of bugs with improvements in Runtime Sanitization and the Clang Static Analyzer. The Thread Sanitizer will help you find data races and other concurrency bugs. The static analyzer has been extended to search for localizability issues, check nullability, and find memory leaks in MRR code.
Edit Scheme – Diagnostics tab
“Enable Thread Sanitizer” checkbox
Build and Run
View all of the generated runtime issues
Can choose to break on every issue

What could be causing the memory leak in my iOS project? I failed to locate any dubious custom methods using Instruments

According to this answer, locating the method causing memory leak is pretty simple with the help of Instruments.
But in my situation, the "extended detail" column doesn't show any of my custom methods, as shown below:
How should I locate the leak point now?
Thanks,
snakeninny
The key is to launch Instruments via Xcode -> Product -> Profile. And then choose Leaks manually, you'll be able to see all the leaking symbols now.

Memory Warning on the device, not with Instruments

I have a huge synchronization process in which I download and unzip 400-500 XML files and then parse it. With this data Im going to create a lot of core data objects over the RestKit API. At the beginning, I had a memory warning with live bytes of 450mb+ because I did not using autorelease pools and only tried to save core data on the end.
I fixed that, saving now frequently to core data and using #autoreleasepool blocks. When im running my app now with instruments, I can see how the live bytes only being 20mb-30mb, always releasing memory and never going to size up. The process just works. But when I start the app without instruments, after a view files I get a Memory Warning. Later on the app crashs.
What is the differene between running the app with and without the instruments tool? Why does it end in different results?
I'm adding this answer because I'm so happy that I came across this page.
What #borrrden suggested is partially true. You can configure which Build settings it will use when you profile. To configure this, goto Xcode and open the Edit Scheme dialog and select in the left menu Profile XXX.app. You will see you can choose a Build Configuration (either Debug or Release).
What #hooleyhoop commented was more crucial to find the solution. Even if your Profile Build Configuration is set to Debug, there is still a difference between Profiling and a default Run from within Xcode. You can specify Diagnostics in the Run section. Right there, there is an option called Enable Zombie Objects under Memory Management. Make sure that this option is unchecked.
These diagnostic Run settings are not used while profiling. That is the explanation for the behavior you are experiencing. There isn't a Diagnostics tab on the Profile section as well.
The result is that my game (Gump) crashed after 5 minutes of doing nothing in the main menu with Zombie Objects enabled. Once I disabled Zombie Objects, my game runs as far as I know for an infinite amount of time. After 45 minutes, still no Memory Warnings.

Crashing on simulator, not on device

My app crashes (randomly by the way) when running on the device, the crash is not reproduce-able 100% of the time. But it only seems to occur on the device, not in the simulator.
When I run in the simulator with NSZombies I never see problems. Could someone shed some light into my points below.
Device has limited memory, maybe it's crashing because of this.
What would be considered a big memory allocation that would cause a crash?
Would memory leaks/big allocation cause a memory corruption?
All my crashes are always EXC_BAD_ACCESS but like I said, never happens on simulator so I can't run zombies. (or is there another way?)
Note I have also simulated low memory warnings on the simulator to see if that's causing issues.
This is driving me nuts. Any help would be appreciated.
I know where it crashes but I need to know which other classes released this object.
Override -[release] -[autorelease] and -[retain] for your object (or you could do this for NSObject if you didn't know which object), then log them, set breakpoints.
If you identify which object is being released at each point, add timestamps/ object IDs/retaincount to the log statement, then you might be able to throw all of the data into a spreadsheet and then to get the same sort of data that Instruments would give you.
Shame you have to build for 3.0. Almost nobody uses 3.x anymore, and ARC (while not a silver bullet for all issues) is way better than non-ARC.
Also here's a tip: delete the app from your simulator and reinstall it. I had an issue where some of my bundle resources were missing in my project but the Simulator was hanging onto them between builds. If you tried to load a .xib that is no longer in your project, I could see it crashing...

Is it possible to use XCode's Instruments with breakpoints enabled?

I'm trying to optimize the memory usage of an iOS app, and I'd like to see what the app's total memory usage is at specific points in the code. I was thinking I should be able to set breakpoints, profile the app with Activity Monitor, and just look at the memory use when each breakpoint catches. But when I run Instruments, it seems breakpoints no longer stop execution, so it's hard to know exactly when memory usage is changing.
Is it possible to use breakpoints and Instruments at the same time? If not, is there a clever way of writing some code to insert a marker into the Instruments timeline when specific events occur?
I also ran into this issue today, and after a bit of searching I found this solution. Text below is a quote from the post:
Breakpoints Do Not Break. Instruments utilizes debug information from
your debug build, however, it does not stop at break points you set.
This is because while you are loading your application into
Instruments from the menu in XCode, Instruments simply uses the path
of the current executable as its start path and loads it externally
from XCode. The menu in XCode is really there as a convenience
mechanism. This is not a big deal as you can always run again in Debug
mode after your instruments session should you want your application
to break. It’s just something to make a note of.
NSLog Statements Do Not Show In The Debugger Console. If you want to
see your NSLog statements, you will need to load the system Console
application (/Applications/Utilities/Console).
Reference: http://www.cimgf.com/2008/04/02/cocoa-tutorial-fixing-memory-leaks-with-instruments/
Well, you aren't running under control of the debugger.
One approach might be to add alerts at the key points, and take a heapshot then (manually).
Or there may be some dtrace wizardry.

Resources