Skip to content

Plugging memory leaks in your iPhone/iPad app

February 5, 2011
by

I’ve been doing a lot of iOS development recently, and just got around to looking at all the memory leaks in my app! Ah, quite the education.

Turns out XCode has some awesome tools for tracking down memory leaks. Today I’m gonna give a short tutorial on using Instruments to find and fix your leaks.

Just fire up XCode with your project, build, then select “Run -> Run with Performance Tool -> Leaks”. This will fire up the Instruments app (a separate app) and automatically create a “Leaks” instrument, and it will start your app in the simulator.

Run your app for a bit, then switch over to the Instruments page and click the “Record” button to stop recording.

Now select the “Leaks” instrument, and you’ll get a display like this:

The main view is the table towards the bottom. I find the “Leaked Blocks” view the most helpful.

That table will list all the leaked objects from your app. Now “leaked” just means that there’s no more references in your app to a particular item on the heap, but the reference count for that item is greater than 0 so the system can’t remove it.

In the example above, we can see very simply that my FeedViewController is leaking an instance of UIBarButtonItem.

Now here’s where it gets interesting. Click that little arrow in the Address column of the table and you get a display like this:

This shows the reference count history for that object. The first row shows that we alloc’d the button in the FeedViewController. The next two rows are down in the system, a “retain” followed by a “release”. Presumably this where the UINavigationBar retained the button while it was showing it.

All reference counts for your objects should start at 1 after alloc, and then eventually get back to 0. When they don’t is when you have a leak. The ref counting is equalized in the system, so we can infer from the history that we’re missing a “release” in FeedViewController. And sure enough, here’s the code:

self.navigationItem.rightBarButtonItem =
		[[UIBarButtonItem alloc]
		 initWithBarButtonSystemItem:UIBarButtonSystemItemSearch...];

Classic. Remember “Alloc” always sets the ref count to 1, so you need either a release or an autorelease to decrement it. The easiest fix here is just this:

self.navigationItem.rightBarButtonItem =
		[[[UIBarButtonItem alloc]
		 initWithBarButtonSystemItem:UIBarButtonSystemItemSearch...] autorelease];

Rebuild, run with Leaks, and sure enough the leak is gone. After working with this tool you start to understand the patterns indicative of typical errors. Can you guess the problem just by looking at this ref count history?

In this case we are alloc’ing the object and assigning it to a “retain” property. You can see the ‘alloc’ and the ‘retain’ from the property. And we can see that we called ‘autorelease’ after the alloc, and indeed the autorelease pool called ‘release’ later. So what’s missing? Hmm…seems like their should be a ‘release’ to go with the ‘retain’ from the property setXXX. And indeed, when I checked out the source, we were simply missing the ‘dealloc’ function altogether. The same thing would happen if you didn’t use ‘self.property = nil’ or ‘[self.property release]‘.

I’ve worked out some good rules-of-thumb when using the Leaks tool:

  1. Test small sections of code one at a time. This makes things much easier.
  2. In the Leaked Blocks list, look for the top-most objects first. Often you’ll find that object B was reported leaked, but that happened because object A which contains B was itself leaked. So always start at the top of the object graph.
  3. Click into the history of a leaked object and carefully match reference count increments to decrements. This will usually show you where the problem is.
Advertisement
One Comment leave one →
  1. Chuck Jerian permalink
    April 13, 2011 4:47 pm

    The pictures in dropbox for this item are not there anymore:
    http://dl.dropbox.com/u/1892875/Screenshots/z1xp.png

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.