The lifespan of an object owned by NSMutableArray, or why Objective-C annoys me and Java makes me happy.

Hard to find memory bug on the iPhone.

I had to find it by (a) building the map file for the distribution of the iPhone product, and (b) walking for an hour around Santa Monica (pretty day, though a bit on the warm side) waiting for the map software component to crash.

I finally found it. It’s the sort of memory bug that Java programmers never have to concern themselves with.

So suppose you’re writing a queue, and you use an NSMutableArray. (In Java you’d use a LinkedList object, which would be faster, but I digress.) Removing the object from the NSMutableArray, I wrote:

MyObject *obj = [myMutableArray objectAtIndex:0];
[myMutableArray removeObjectAtIndex:0];
UseMyObject(obj);

And all is right in the world, correct?

Um, not quite.

See, there is thing thing called the autorelease pool. It’s quite clever: it holds a list of all the objects that, after this current event is finished being processed, the objects will be released and potentially deleted from the system. So when you get a return value back from some function, unless its a function which explicitly gives you ownership of the object, you can safely use that object until the end of the event processing loop, which certainly won’t happen until after your routine returns, right?

Um, not quite.

NSMutableArray notes in its documentation that on a call to the remove function removing that item from the array, release is called immediately on the object, which means my object obj above has been released. Now what makes this a hard to find bug is that while the object may have been deleted and its memory released, the object itself still lingers in memory unless you use a memory debugging library.

And unfortunately for me (1) the conditions causing this routine to be called is only triggered when walking around with our new software package, and (2) the various memory debugging libraries only work under the iPhone simulator.

The workaround?

MyObject *obj = [myMutableArray objectAtIndex:0];
[[obj retain] autorelease];  // before removeObjectAtIndex
[myMutableArray removeObjectAtIndex:0];
UseMyObject(obj);

Feh.

This is exactly the sort of stuff that garbage collection helps with, and is the primary reason why I like Java: no messing with object lifecycle management. Unfortunately garbage collected Objective C isn’t available on the iPhone, which means that so long as I’m trying to write Objective C code that runs on the iPhone and may also run on the Macintosh, I cannot use garbage collection in my Objective C development.

1 thought on “The lifespan of an object owned by NSMutableArray, or why Objective-C annoys me and Java makes me happy.”

  1. Thanks for the posting about NSMutableArrays. I had read the doc line about the remove function but had not fully understood the implications.

    I liked your comments on social networking sites too. What are these people thinking?

Leave a Reply