Question

Here is the gist of some code I'm writing. I'm concerned that I am not properly addressing the retain/release issues with the array class method on NSMutableArray. Is the following actually leaking memory?

for(a while) { 
    // do stuff
    NSMutableArray *a = nil;
    // do stuff
    if (!a) {
        a = [NSMutableArray array];
    }
} // for(a while)
Was it helpful?

Solution

You wouldn't leak memory in this code, and releasing the array yourself will cause a crash when the array is autoreleased at the end of the run loop.

Most Cocoa classes provide a couple of ways of making a new object, and are very consistent with this convention:

  1. [[NSSomeObject alloc] init] : you are responsible for releasing the object (instance method).

  2. [NSSomeObject someObject] : the object will be autoreleased for you, usually at the end of the run loop (class method). It's roughly equivalent to [[[NSSomeObject alloc] init] autorelease].

The proper use of the instance method would be:

a = [[NSMutableArray alloc] init];
// do stuff
[a release];

The proper use of the class method would be:

a = [NSMutableArray array];
// do stuff, array is in the autorelease pool

Note that Apple has recommended you stay away from the convenience methods as much as possible to improve performance. This is controversial advice, may not save much processor time, and separates the alloc-init from the release on an object you may not actually care much about keeping.

OTHER TIPS

From the Cocoa Memory Managment Rules:

You take ownership of an object if you create it using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message. You are responsible for relinquishing ownership of objects you own using release or autorelease. Any other time you receive an object, you must not release it.

Therefore with the line:

a = [NSMutableArray array];

you do not take ownership of the array, and it will be passed to you autoreleased. The memory will be handled for you automatically by the autorelease pool, and once it is no longer being used, it will be released for you. If you want to keep the array outside the current event, however, you must retain it, otherwise it will be released for you.

Yes, if you want it to stick around.

The returned object is an autoreleased object which will get deallocated when its autorelease pool gets purged.

All the array class methods that begin with "array" return these types of autoreleased objects.

Read this doc by Apple.

That's valid. It may help to just manage things manually when you have questions, to learn.

There is a convention:

  • init prefixes (init, initWithString:) indicate a retain count of 1, where
  • objectname prefixes (string, stringWithString:) indicates an autoreleased object

I have had the habit, for years, to release what I can at the call site, rather than pushing it to be autoreleased. Some autorelease issues then become painfully difficult to track down. Sure, autorelease is a convenience to the programmer in this case (provided nothing goes wrong), but adversely affects reuse, clarity, and performance (moreso in large codebases/programs).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top