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.
MyObject *obj = [myMutableArray objectAtIndex:0]; [[obj retain] autorelease]; // before removeObjectAtIndex [myMutableArray removeObjectAtIndex:0]; UseMyObject(obj);
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.