views:

2114

answers:

3

I have one crash in my iPhone application that does throw an NSException. The crash reports are completely ambiguous in where the error is and what exactly is causing it. Is there a smart way for me to set a top level exception handler somewhere to see what is causing it? I can't replicate the problem myself, but a few of my beta users certainly can.

What's a smart way to handle a problem of this nature?

+1  A: 

Have you tried NSSetUncaughtExceptionHandler?

kperryua
+10  A: 

It seems like you are asking two questions here: how to set a top level exception handler; and how to deal with the issue of determining what the root cause is.

Catching the exception can be done in a few different ways, but for this the best approach would appear to be to set an exception handler using NSSetUncaughtExceptionHandler.

When an exception is raised in your app, it is handled by a default exception handler. This handler does nothing more than log a message to the console before the app closes. You can over-ride this by setting you own custom exception handler using the function stated above. The best place to do this would be in the app delegate applicationDidFinishLaunching: method.

- (void) applicationDidFinishLaunching: (UIApplication *) application
{
    NSSetUncaughtExceptionHandler (&myExceptionHandler);
}

Once you've set a custom handler, you'll want to expand on the default output in helping you determine what the cause is.

- (void) myExceptionHandler (NSException *exception)
{
    NSArray *stack = [exception callStackReturnAddresses];
    NSLog(@"%@", stack);
}

Unfortunately compared to OSX the iPhone appears quite limited in respect to producing a nice stack trace. The code above will produce some seemingly junk output; however, you can run this output through the atos tool, and you should be able to generate a useful stack trace from it.

Another option is to follow the instructions on http://rel.me/2008/12/30/getting-a-useful-stack-trace-from-nsexception-callstackreturnaddresses/ which will help to produce a nice stack trace automatically.

As this is going out to beta testers you may have to tinker about to get it working for you.

You say that you've not been able to replicate the problem yourself, only your users. In this case you may find this technical note from Apple useful:

http://developer.apple.com/iphone/library/technotes/tn2008/tn2151.html
fatalexception
Google Toolbox for Mac's GTMStackTrace is a big help sometimes :)
rpetrich
Why iterate through the stack yourself, when you can do NSLog(@"%@" stack) ?
AlBlue
Why not indeed. Edited, and thanks for the input.
fatalexception
Based on the lack of feedback I assume that this is still a problem. I've added a reference to Apple technical notes that may help.
fatalexception
+2  A: 

In XCode, you should always set a global breakpoint for objc_exception_throw. Then you (usually) get a far more meaningful stack trace as to what is actually trying to throw an exception.

You can still get exceptions that originate in timer code or other places without your own code anywhere in the trace, but if you look at the method chain you can usually figure out generally what the exception is about (like having a notification sent where the target is gone).

Kendall Helmstetter Gelner