(if this helps you, even to save a little time, please leave a comment)

Recently, I was working on an iPhone application for a client when I ran headlong into a crash in objc_msgSend.  It was a hair-pulling bit of frustration for me as it seemed so hard to debug for a long time.  Every time I encountered it, this was all I saw on the stack:

Debugger Stack for objc_msgSend problem

Debugger Stack for objc_msgSend problem

I saw several posts online which gave me more than few hints.  It seemed very clear that I had over-released something, but all the zombies and other flags didn’t really make it clear which thing was getting over-released or where.  I could tell what it was, but nothing much else until I struck on this idea while taking a walk:  if the crashes are always related to the release of an auto-release pool, then I need to control the auto-release pool. I can’t wait for this _NSFireDelayedPerform thing to decide to release it. (Steve Maguire’s  “Writing Solid Code” has been one of my favorite industry books for a long time.)

So in essence, I started bracketing all my suspect code like this:

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

<code to test>

[pool release];

Sure enough, my debugger stacks went from looking like the one above to looking like this:

Debugger Stack With Manual Pool Release

Debugger Stack With Manual Pool Release

That’s a LOT better. Now I know where to look.  Further application of layers of pools narrowed down the target pretty quickly.

In the end,  I found that my mistake was a call like this in an initializer:

NSMutableArray *memberArray = [[NSMutableArray alloc]  initWithCapacity: 5];

which isn’t wrong.  However,  I never actually filled the allocated array entries.  When it was released later, it caused my crash.  Changing the code to to allocate the array later, when I had items to fill it,  fixed the problem.

There is one little problem with this technique that I see: you have to be careful how you bracket things with the pool-release calls.  If you release a pool, then try to use something that was allocated on that pool, you may be trying to use something you’ve already released.  The easiest way I saw to use it was to put them around a call to a routine or a message.  When I had to use them inside a block of code, I had to be careful that allocations and releases that used the pool would all be inside the bracketing calls.

I hope this helps someone else find a solution.  If it did, please leave a comment.