Tag Archives: iPhone memory

Retain, release. Part II

Memory Management

I’ve written previously about memory management on this blog but I thought it was about time to do it all again with a new slant. So today I’m sitting down to write about finding and fixing memory leaks with the tools provided by Apple namely Leaks. Clearly after reading my last post about memory management on iPhone you won’t have any leaks..but just in case here’s how to track them down and plug them.

So What Is A Leak?

Memory is managed on the iPhone using a reference counted system, each object that is created has a reference count which is freely changeable using the magic functions (release, retain, etc). Memory is said to be leaked (or orphaned) if all references to it are lost. This usually happens when a piece of code does a new, malloc, or alloc without a matching delete, free or release respectively.

This matters to the aspiring iPhone SDK developer since every time your app leaks some memory your app’s available memory effectively shrinks since this memory is in use but is not write/read-able or for that matter deleteable, so if you leak memory there’s nothing you can do about it until the iPhone clears all memory allocated to you when you exit.

If you leak memory in a loop or in a frequently called function this can seriously harm the longevity of you app, since the iPhone will likely kill your app for excessive memory usage. Or worse it will be rejected from the app store!

How To Find a Memory Leak

To find your memory leak you will need to open up instruments and pick the Leaks tool from the menu.

Opening the Leaks tool in Instruments

Opening the Leaks tool in Instruments

Once you’ve done that you should be presented with the following screen, and you are ready to hunt down that memory leak.

Opening Leaks tool from Instruments

Opening Leaks tool from Instruments

Simply fire up your test binary (you can do it on target or on emulator) by picking from the list as shown

Open the binary you want to measure

Open the binary you want to measure

By default Leaks will check the memory allocated to your app for consistency every 10 seconds. You can change this should you wish, but there is really no need. You may also set it to manual should you only want to test specific blocks.

When Leaks finds a memory leak it will automatically spring up in the interface as shown below,

Leaks tool has found a leak

Leaks tool has found a leak

From here you might be feeling a little let down; a memory leak and all I get is a red blob and some basic info…rubbish! Fear not, Leaks has the almighty

Extended Detail View

Hidden in the smallest of icons is the mightiest of tools behind Leaks. The extended detail view. By clicking on this icon you will be presented with something like this,

Extended detail view shows the stack

Extended detail view shows the stack

If I click on the entry for the first memory leak Extended Detail View shows a complete stack right up to the call where allocation of the leaked memory occurred. From here it is easy to see that the leak occurred inside [UIColor initWithPatternImage], looking further into the stack the last call within my test code was made from [Bombs_Away ViewController viewDidLoad].

The function call causing the leak has been found

The function call causing the leak has been found

Double click on the function in the stack and you will be presented with the line of code responsible for the leak. Inspecting the line shows that I have alloc’d a UIColor without releasing it later when my block went out of scope.

Solve the issue in your code

Solve the issue in your code

Solving the Leak

Now that you have found the code responsible fixing the leak is child’s play…well in this case. Simply changing the code to,

UIColor *bg = [[UIColor alloc] initWithPatternImage: [UIImage imageNamed:@""]];
self.view.backgroundColor = bg;
[bg release];

by adding the release will solve the issue and resolve my memory leak!

Memory Allocation on iPhone

Getting the retain count

I’ve spoken here a few times regarding memory usage on the iPhone platform. It’s a fickle beast at times, but there is a great snippet of code anyone struggling to get to grips with memory management should know. The below code allows you to log (or do anything with) the retain count of an object. This can be used to ensure memory is not leaked or to see if an object is over released causing you app to crash.

- (void)applicationDidFinishLaunching:(UIApplication *)application {
        UIViewController *viewController = [[UIViewController alloc] init];
        NSLog(@"retainCount:%d", [viewController retainCount]);
        [viewController retain];
        NSLog(@”retainCount:%d”, [viewController retainCount]);
}

Memory allocation and control is one of the greatest challenges to newcommers so bear this little trick in mind next time you run into issues with memory management.

Retain, release. A guide to Cocoa Memory Management

Intro to Cocoa memory management

For those coming to the iPhone (and Obj-C/Cocoa) platform, especially those coming from any platform with garbage collection will definitely get caught out by Cocoa’s memory management model. This will probably hit those developing using the iPhone SDK hard, with its limited memory catching leaks will be ever more important as when memory runs low your app will have to clean up after itself and exit :( .

For those reading Cocoa code for the first few times calls to methods such as -retain-release and -autorelease might seem somewhat bizarre, but they form the basis of Cocoa memory management. Cocoa uses reference counting to keep track of memory and the code that uses it, a common practice in low memory devices. These calls are all you need to make sure you aren’t causing memory leaks in your code.

Method Description
-retain increases the reference count of an object (by 1)
-release decreases the reference count of an object
-autorelease decreases the reference count of an object by 1 when possible
-alloc allocates memory for an object, and returns it with retain count of 1
-copy makes a copy of an object, and returns it with retain count of 1

Basic Rules

Good things come in three, so here are the three golden rules for memory management for iPhone development

  1. Within a block of code, the use of -copy-alloc and -retain should be balanced by use of -release and -autorelease.
  2. Objects created using convenience constructors (e.g. NSString’s stringWithString) are autoreleased.
  3. Implement a -dealloc method to release the instance variables you own when your class is destroyed

Examples

Maintaining the reference counts for an object

- (void)helloWorld{
NSString *string;
//alloc the memory for sting object
string = [[NSString alloc] initWithString:@"Hello World"];
// we created string with alloc so we need to release it so the
//referance count for this code block match
[string release];
}

Creating an object using a convienience constructor, autrelease is used.

- (void)helloWorld
{
NSString *string;
// object is created with a convenience constructor, will be autoreleased
string = [NSString stringWithFormat:@"Hello"];
// autorelease, no need for release
}

Working with arrays, and objects stored in arrays. Objects placed inside an array in can be released after addition since the array object will add 1 to the reference count


NSMutableArray *array;
int i;
for (i = 0; i < 10; i++)
{
NSNumber *n = [[NSNumber alloc] initWithInt: i];
[array addObject: n];
[n release];
}

Since its quite a difficuly area for people new to Cocoa/iPhone I’ll add more memory management tips as and when, and I’ll certainlly attempt to answer any questions left in the comments.