malloc_error_break, double free, iPhone 3.0…maybe you fucked up NSTimer?

June 29, 2009 at 11:13 am (iPhone development, Software Engineering) (, , , , , , , , )

Yesterday, while working on a client project that had been rejected from the app store, I was doing some initial diagnostics and came across this wondrously useless error message in the console:

malloc: *** error for object 0x529d20: double free
*** set a breakpoint in malloc_error_break to debug

Apparently, when doing the quick cert-signing and testing previously, we hadn’t looked at the console on all of the versions…because this particular error is only a warning on the iPhone OS 2.2.1, and a crashing error on 3.0.  Don’t have any idea why the difference across versions, but it’s there.  So when we ran this on an iPod Touch 2.2.1, it seemed to execute fine, you had to be looking at the console, without being alerted by the debugger…tricky little bitch.

Now, I know what a double free is, but I have no idea where to find malloc_error_break…and Google doesn’t fucking help much, it’s just a bunch of people posting build errors on forums, with no useful responses.  I’m hoping this post will make it up the list, and you will potentially find something useful here, instead of just a cry for help.

So…faced with an easily recurring error, I was pretty confident I could knock it out in short order.  The malloc_error_break message was sort of helpful, but not enough.  I could set breakpoints, and never quite nail down the error…I could break before it, and after it (on 2.2.1)…but not on it.

The useful piece of information in that error message is twofold…one, the double free indication.  And two, more importantly, the memory address of the object. That is how I found the source of the error.  I couldn’t find malloc_error_break, but I could guess which objects might be getting double-freed by looking at the code.  It turned out, the original engineers had written this code to stop an NSTimer:

- (void) stopTimer
  if (ptrTimer)
    [ptrTimer invalidate];
    [ptrTimer release];
    ptrTimer = nil;

this code, is wrong.  The release in the middle is extraneous, and is what was causing the double-free.  The invalidate call is all you need to stop the timer, the setting to nil is nice for sanity.  I looked at the memory addresses of the two initial NSTimers set during app load, and noted them at the breakpoint right before the crash.  And bam, one of the addresses showed up in the error message as the object that had been double-freed.

So, that was it.  There happened to be about 7 different timers floating around the app, all mistakenly stopped in the above way, so the app was absolutely going to crash, no matter what you did.  Commenting out the release was all it took for me…and just over an hour later, I had the app all ready for submission to the app store.  We sent it in this morning, hopefully it should be done by friday.


Permalink 4 Comments