views:

220

answers:

2

I tried use "PLCrashReport" to collect the crash info then make the app more stable, but turns out that the report is like this(dont even has a call stack,how am I suppose to use it?):

The "Exception:" part,Exception: (null): (null), which should be "exceptionName" and "exceptionReason", at most time are "null", dont know why, sometimes there will be a normal value but also I think not quite useful...

Crashed on 2009-11-13 23:43:04 +0800 - Signal SIGSEGV (code SEGV_ACCERR, address=0xffffffffc0f4186b)

  • Exception: (null): (null) - Thread 0:

    • Crashed: 1
    • Stack (54 frames):,\n 806128664,\n 807756495,\n 816280840,\n 816247 068,\n 817901396,\n 807756495,\n 816280840,\n 817911108,\n 816247068,\n 816285160,\n 816406620,\n 807756495,\n 806130012,\n 119241,\n 812165747,\n 812164839 ,\n 812379009,\n 818127880,\n 807885435,\n 807923065,\n 818122176,\n 818130772,\n 816625560,\n 816626608,\n 816627024,\n 816641892,\n 816651496,\n 816654628 ,\n 816654224,\n 146455,\n 807923363,\n 816119156,\n 816119004,\n 818227300,\n 807923363,\n 816119156,\n 816119004,\n 816524332,\n 816525956,\n 816521588,\n 816212028,\n 816151252,\n 816147980,\n 827758796,\n 827769116,\n 837343488,\n 821391952,\n 807840887,\n 807836793,\n 807834407,\n 827752032,\n 816118388,\n816157144,\n 20421
A: 

I haven't used it but I'm pretty sure you're not getting any detail because you had a segmentation fault that took out everything down to the registers. The PLCrashReport instance can't report because it died along with everything else.

The PLCrashReport instances runs within the Application itself so if the app goes down hard you won't get any detail.

TechZen
Thank you!seems I need to go over the code carefully again and again...
springrider
+1  A: 

What's a stack trace?

Whenever one of your methods gets called, it puts this onto the stack. A stack trace is a way of finding out which class and method your app crashed in, which often narrows down the bug to a single line.

Of course to do this, the stack trace needs to be readable, rather than a whole load of hex numbers.

Check out atos.

To prevent this happening again, you could interpret this Call Stack using atos. See the Stack Traces page of the Cocoa Dev wiki for a discussion and code on how to convert these numbers into meaningful methods.

You'll need to figure out a way of integrating this with the crash reporter. I use UKCrashReporter and I've modified Uli's code so that if there's an uncaught exception it adds the readable stack trace onto the crash report.

Code Sample

I've taken inspiration from the ESStackTrace class and here's what I do:

-(void)logAndSaveStackTrace {
    NSString *stackTrace = [[self userInfo] objectForKey:NSStackTraceKey];
    NSString *atosCommand;
    if (stackTrace) {
        // If the stack trace key is present, pull out the addresses and convert to method names using atos.
        atosCommand = [NSString stringWithFormat:@"/usr/bin/atos -p %d %@ | tail -n +3 | head -n +%d | c++filt | cat -n",
                         [[NSProcessInfo processInfo] processIdentifier],
                         stackTrace,
                         ([[stackTrace componentsSeparatedByString:@"  "] count] - 4)];

    } else {
        // If there isn't a stack trace key or it's nil, try and work out the stack using the internal callStackReturn addresses method.
        NSArray *stackTraceArray = [self callStackReturnAddresses];
        atosCommand = [NSString stringWithFormat:@"/usr/bin/atos -p %d %@",
                       [[NSProcessInfo processInfo] processIdentifier],
                       [stackTraceArray componentsJoinedByString:@" "]];
    }

    NSString *readableStackTrace = [ShellTask executeShellCommandSynchronously:atosCommand];

    NSString *exceptionMessageForCrashReport = [NSString stringWithFormat:@"An exception of type %s occured.\n%s\nStack trace:\n%@", 
                                                [[self name] cStringUsingEncoding:NSUTF8StringEncoding], 
                                                [[self reason] cStringUsingEncoding:NSUTF8StringEncoding],
                                                readableStackTrace];

    [[NSUserDefaults standardUserDefaults] setObject:exceptionMessageForCrashReport forKey:@"uncaughtExceptionReport"];
    [[NSUserDefaults standardUserDefaults] synchronize];

    // Log the exception to the console too.
    NSLog(@"%@", exceptionMessageForCrashReport);
}

Dependencies Ahoy!

Of course, one of the problems with this approach is that you're introducing a dependency on atos. I've been told that it's installed as standard on 10.5 and later, but this might be wrong. Eventually I'm going to make a little installer which adds atos if my app can't find it.

John Gallagher