Wednesday, April 27, 2011

When things blow up in Objective-C with a stack trace like "objc_msgSend ??"

I got an "Program received signal:  “EXC_BAD_ACCESS”." error after a small change I made to some code:

NSLog(@"downloadModel from %@, modelPlistUrl");

As you can see, the format descriptor passed to NSLog was expecting to be followed by an NSObject parameter and I failed to provide one. The result is unforgiving:

The call stack appears to have been corrupted, leaving very little to aid in debugging the issue. Here's where it pays to test often, after small changes and to use SCM, that would allow you to see recent changes and hopefully find the problem.

It's pretty disappointing that NSLog fails so badly. According to the docs, %@ placeholders in the format specifier string are meant to be filled with the content returned by "descriptionWithLocale: if available, or description otherwise. Also works with CFTypeRef objects, returning the result of the CFCopyDescription function". So the runtime obviously takes whatever happens to be on the stack frame where the expected parameter should have been and it manages to trash the stack in the process.

I would have thought that the static analyzer invoked with "Build and Analyze" would catch it, but it doesn't either. So your best bet is to code in small increments, test often and use your intuition when cornered.

No comments: