Debugging Objective-C on the iPhone is usually OK, but there are some painful moments with those hard to find bugs. Today’s bug went something like this:
1.) Open iPad app in portrait mode
2.) Click on “My Blogs” top left and choose a blog
3.) Make sure you are on the comments view and click ‘edit’ at the top right of that dialog (the button changes to ‘cancel’)
4.) Then when the list is in edit mode rotate the device to landscape mode
5.) The ‘cancel’ button now says ‘edit’. click on this ‘edit’ button.
6.) It should work fine, now simply put the device in portrait mode again and continue from step 2 above.
It should crash the second time you do this, if not it will crash on the third time.
Nice catch. When you are debugging with Xcode, most of the times you get some useful message in the console or at least some stack trace pointing where things went wrong. Today’s message was this useful
Program received signal: “EXC_BAD_ACCESS”.
And the stack trace was no better:
NSZombie to the rescue
If you have worked with Cocoa for a while, you might be familiar with NSZombie, but since the development tools have changed in the last years, some of the tutorials around are not accurate.
NSZombie is a Cocoa trick that turns any object going to be deallocated into a NSZombie instance. You are going to crash anyway, but instead of Xcode just complaining that you tried to access the wrong memory address, you get something a bit better like this:
2011-02-25 01:27:57.063 WordPress[10496:207] *** -[CFString isEqualToString:]: message sent to deallocated instance 0xcf1b0c0
Not much, but at least you know that the guilty object was a string.
But there’s more to it. First, you enable NSZombie by double clicking your executable in the project info, and then in the “Arguments” tab setting the NSZombieEnabled environment variable
Instruments, that wonderful tool
Sometimes, it will be enough just knowing which class was released more than it should. But when it’s not, Instruments can help.
Sadly, Instruments can only do NSZombie magic on the simulator, but for this example that was not an issue. From Xcode, go to the “Run” menu, then “Run with Performance Tool”, and there you’ll probably see Zombies disabled. Don’t worry, select “Allocations” and you will be fine.
As soon as the app starts running, stop it by clicking on the big record button, we need to set up a few things first.
Click on the little “info” button besides Allocations, and enable “Record reference counts” and “Enable NSZombie detection”. Start the app again (with the same big record button) and repeat the steps that led to the crash. Same story, but this time…
And when you click on that memory address, it will show you the history of the object, when and where it was created, and every time it was retained or released until it crashed
And even more, if you double-click that line, it will take you to a code editor, at the exact line when it was released. Now, that was helpful
And as you can see from this piece of code, we were releasing email on dealloc, but we didn’t retain it on setEmail. Delete that [email release] and problem fixed.
Oscar Goldman
January 30, 2012
Thanks, but I would’ve expected Xcode 4 in 2011.
Jorge Bernal
January 30, 2012
Good point. It’s pretty much the same, instead of editing the Executable you edit the Scheme, but I believe the rest is similar
kadnan
August 7, 2012
I dont see “Enable Zombie Detection” in Instrument? How do I do it?
kadnan
August 7, 2012
Ok i was enable to view it(Figured out I was testing on device) but when I ran my app on Simulator it did not notice any Bad Access but it showed only on iPhone. The Recording on Instrument kept running and running. How will I figure it out?
Jorge Bernal
August 7, 2012
Unfortunately, some annoying bugs don’t appear on the simulator, but I haven’t found one of those for a while.
Maybe you’re doing something different? (like using the camera, which is not available on the simulator)
Marchy
November 6, 2012
Awesome post. You TOTALLY saved me on something I was going crazy debugging. Way to make/save my day. 🙂
Peter
April 25, 2013
You just saved me a whole lot of time 🙂