
I’m getting ready to send my iPhone Application to the first beta testers and so I started thinking about crash reports.
On the Mac you have two options to get the crash report of your application. The first one is to check on startup if there is a new crash report file in ~/Library/Logs/CrashReporter for your application and simply send it. (Example: HDCrashReporter , UKCrashReporter)
The other option is to use NSExceptionHandler, which let you report the problem as it happens. (Example: A simple debugging tool for Cocoa)
On the iPhone you can’t access the crash report file form your application because it’s running in a sandbox (rdar://problem/6296554). iTunes synchronizes the crash reports of all applications, so although a user could in theory send it to you, this seems rather complicated to me (Locations of Crash Logs).
So what about NSExceptionHandler? Well, there isn’t a NSExceptionHandler in the iPhone SDK. But wait, there is a NSUncaughtExceptionHandler!
/* GeSHi (C) 2004 – 2007 Nigel McNie (http://qbnz.com/highlighter) */
.objc .de1, .objc .de2 {font-family: ‘Courier New’, Courier, monospace; font-weight: normal; font-size: 11px; }
.objc {font-family: monospace;}
.objc .imp {font-weight: bold; color: red;}
.objc li {background: #f8f8f8;}
.objc li.li2 {background: #f8f8f8;}
.objc .kw1 {color: #0000ff;}
.objc .kw2 {color: #0000ff;}
.objc .kw3 {color: #0000dd;}
.objc .kw4 {color: #0000ff;}
.objc .kw5 {color: #0000ff;}
.objc .kw6 {color: #0000ff;}
.objc .co1 {color: #ff0000;}
.objc .co2 {color: #339900;}
.objc .coMULTI {color: #ff0000; font-style: italic;}
.objc .es0 {color: #666666; font-weight: bold;}
.objc .br0 {color: #002200;}
.objc .st0 {color: #666666;}
.objc .nu0 {color: #0000dd;}
html>body .entry .objc ol li { margin: 0 0 0 0; }
.syntax { padding-left: 15px; background-color: #E8E8E8; text-align:left; }
-
int frameCount = [callStackArray count];
-
void *backtraceFrames[frameCount];
-
-
for (int i=0; i<frameCount; i++) {
-
backtraceFrames[i] = (void *)[[callStackArray objectAtIndex:i] unsignedIntegerValue];
-
}
-
-
// report the exception
-
}
-
-
@implementation AppDelegate
-
-
- (void)applicationDidFinishLaunching:(UIApplication *)application {
-
NSSetUncaughtExceptionHandler(&MyUncaughtExceptionHandler);
-
}
-
-
@end
Now you can get the backtrace in MyUncaughtExceptionHandler with backtrace_symbols(3). (Example)
You still have to symbolicate the crash reports.
As a big fan of Fogbugz, I also wanted to use BugzScout. It’s just a HTTP POST, but here is the code:
-
[post appendString:@"ScoutUserName="];
-
[post appendString:urlEncodeValue(@"Your BugzScout User")];
-
-
[post appendString:@"&ScoutProject="];
-
[post appendString:urlEncodeValue(@"Your Project")];
-
-
[post appendString:@"&ScoutArea="];
-
[post appendString:urlEncodeValue(@"Your Area")];
-
-
[post appendString:@"&Description="];
-
[post appendString:urlEncodeValue(description)];
-
-
[post appendString:@"&Extra="];
-
[post appendString:urlEncodeValue(extra)];
-
-
[post appendString:@"&ScoutDefaultMessage=&FriendlyResponse=0&ForceNewBug=0"];
-
-
//NSLog(post);
-
-
-
-
[req setHTTPMethod:@"POST"];
-
[req addValue:@"application/x-www-form-urlencoded" forHTTPHeaderField: @"Content-Type"];
-
[req addValue:postLength forHTTPHeaderField: @"Content-Length"];
-
[req setHTTPBody:postData];
-
-
}
-
-
CFStringRef urlString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
-
(CFStringRef)str, NULL, CFSTR(";/?:@&=+$,"), kCFStringEncodingUTF8);
-
}
Crash Reporter for iPhone Applications (Part 1)
Crash Reporter for iPhone Applications (Part 2)
Hi, Christopher. It seems the link to http://www.cocoadev.com/index.pl?StackTraces is broken. Thanks for taking the time to write this up!
You’re welcome! (Link is fix)
There is another option for the Mac
http://vafer.org/projects/feedbackreporter/
Christopher, this rocks. I’ll implement it right now. Thanks a lot!
Christopher,
Very nice post. Thank you for sharing..
Chris…
I wonder if you could give a bit more detail on how to symbolicate the stack trace you are generating. I managed to get a reasonable stack trace by using the backtrace_symbols function you mentioned, however the symbols for my application (the ones i need) are missing. When i attempt to symbolicate the stack trace generated by the function above i get the following error from the symbolicate utility:
joshua$ symbolicatecrash maildump.txt ICONtact.app.dSYM
No crash report version in maildump.txt at /Users/joshua/bin/symbolicatecrash line 719.
Running the symbolicate utility against a full from the iPhone crash dump however works fine.
Hi Josh,
you are right, it’s not possible to use the symbolicatecrash script if you not format your crash report exactly as the apple one. I current use atos, Debugging and Symbolizing Crash Dumps in Xcode, but I’m searching a better solution for this.
Christopher
Hi Chris,
Have you managed to find a better solution (as mentioned in the above comment)? I’m trying to get this to work with my iPhone application, but I’m a little confused as to how you use this atos tool from the phone. Are you calling the system atos application directly from within your app?
I’m anxious to get this working as it would greatly improve our debugging cycle. This blog is definitely a great starting point. Perhaps one more post would be useful which details the entirety of the procedure in one place.
Thanks in advance.
Hi Glenn,
you don’t use the atos tool on the iphone, you use it on your developer box. After you build the application you see in your build folder a dSYM folder which include the needed information for atos.
I still haven’t automated this…
Christopher
Hi Chris,
Thanks for the post! I’ve just spotted there’s an error in the MyUncaughtExceptionHandler code:
for (int i=0; i<[callStackArray cout]; i++) {
…should be “count”, not “cout”. (I’m guessing that you want to use frameCount as the loop’s check too – it’s unused otherwise.)
Ironically, using the code as it is causes an exception in the exception handler, resulting in an infinite loop of exceptions
Hi Maurj,
I fixed the typos, thx!
Christopher
I just published “ratos”, an open source shell that you can start in a terminal and past an entire Xcode stack trace and it will decode it. Speeds up using atos.
Announcement/Doc is here: http://myutil.com/2009/2/6/announcing-ratos-a-shell-to-decode-iphone-stack-traces
And you can go straight to the code here: http://github.com/face/ratos/tree/master
-Rama
thank you very much for this useful guide.