No exception stacktrace in console under Xcode 4.2/iOS 5?
Asked Answered
B

3

48

Under Xcode 3.x and iOS 4, if an unhandled exception is signaled in the emulator there is an exception stack trace (similar to Java's) produced in the console output.

When I raise an unhandled exception in iOS 5 under Xcode 4.2, running the exact same app code, the stack trace does not occur. (I did figure out how to set an exception breakpoint, but that doesn't produce the traceback in the console.)

Is this merely an Xcode setting I need to make somewhere, or a "feature" of Xcode 4/iOS 5? Is there some way restore this bit of functionality?

Update

Unfortunately, adding an uncaughtExceptionHandler doesn't work. Here is the handler:

void uncaughtExceptionHandler(NSException *exception) {
    NSLog(@"uncaughtExceptionHnadler -- Exception %@", [exception description]);
    // Because iOS 5 doesn't provide a traceback, provide one here
    NSLog(@"Stack trace: %@", [exception callStackSymbols]);
    // Let Flurry look at the error
    [FlurryAPI logError:@"Uncaught" message:@"Crash!" exception:exception];
}                                               

(It turns out it was already present, to do the Flurry thing, so I just added the stack trace.)

Here is where it's enabled (just a few lines below where the handler is declared):

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    // Enable uncaught exception handler to dump stack and let Flurry log the exception
    NSUncaughtExceptionHandler* hdlr = NSGetUncaughtExceptionHandler();
    NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
    NSUncaughtExceptionHandler* newHdlr = NSGetUncaughtExceptionHandler();
    
    // TODO: Test
    NSException* ex = [NSException exceptionWithName:@"AssertionFailure" reason:@"Test" userInfo:nil]; 
    @throw ex; 

I set breakpoints to enable me to check the two retrieved handler values. The first one is nil and the second is an apparently valid address. But when the test exception is thrown the handler (in iOS 5 simulator) never gets control. (Though when I run on the iOS 4.2 simulator it does get control.)

Setting NSExceptionHandlingMask is apparently not possible on iPhone. The prereq ExceptionHandling.framework is not available.

Update 2

This works:

int main(int argc, char *argv[]) {
    
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    int retVal = -1;
    @try {
        retVal = UIApplicationMain(argc, argv, nil, nil);
    }
    @catch (NSException* exception) {
        NSLog(@"Uncaught exception: %@", exception.description);
        NSLog(@"Stack trace: %@", [exception callStackSymbols]);
    }
    [pool release];
    return retVal;
}
Balbo answered 11/11, 2011 at 21:13 Comment(5)
cool, glad that it is solved :-) perhaps you can add it as an answer (not just in the question body).Claymore
I may, if no one else comes up with a fix that makes uncaughtExceptionHandler work.Balbo
Still waiting for some sort of explanation as to why the default dump no longer works and/or why (even more serious) uncaughtExceptionHandler doesn't work.Balbo
the problem you describe seems to affect only the emulator... on a real device it works as it should...Claymore
Nice how you mark other questions (Asking different things) as duplicates as an excuse to point back to this question so that your question will get more visibility and consequently more points for you. Congratulations on figuring out how to game the system, but as a result, you got my question-- which has not been answered-- closed as a dupe, making stackoverflow less useful for everybody.Enterostomy
B
36

This works:

int main(int argc, char *argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    int retVal = -1;
    @try {
        retVal = UIApplicationMain(argc, argv, nil, nil);
    }
    @catch (NSException* exception) {
        NSLog(@"Uncaught exception: %@", exception.description);
        NSLog(@"Stack trace: %@", [exception callStackSymbols]);
    }
    [pool release];
    return retVal;
}

For ARC:

int main(int argc, char *argv[]) {

    int retVal = -1;
    @autoreleasepool {
        @try {
            retVal = UIApplicationMain(argc, argv, nil, nil);
        }
        @catch (NSException* exception) {
            NSLog(@"Uncaught exception: %@", exception.description);
            NSLog(@"Stack trace: %@", [exception callStackSymbols]);
        }
    }
    return retVal;
}

Still waiting for some sort of explanation as to why the default dump no longer works and/or why (even more serious) uncaughtExceptionHandler doesn't work. However, apparently this problem only affects the emulator.

update:

It has been pointed out that if you go to Product -> Scheme -> Edit Scheme, select "Run (Debug)", select the "Diagnostics" tab, and click "Log Exceptions", this will restore the missing Xcode default exception logging, possibly (I haven't tried it yet) eliminating the need for the above hack.

Balbo answered 4/9, 2012 at 17:18 Comment(6)
If you're using ARC just change the autorelease alloc/release to @autoreleasepool {...}.Balbo
Probably just forgot, but I had to do this for the return value retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([YourAppDelegate class]));Antipyretic
This not needed at all. You just have to create the exception breakpoint, see blog.manbolo.com/2012/01/23/xcode-tips-1-break-on-exceptionsVulgar
Just enabling "Zombie Objects" saved me from a problem that was killing me all day!Ciera
This was seriously a HUGE help! Got me to actually find the issue. Thank you @HotLicksLadybird
Thanks very much, I can't believe I had to research for this one, really unbelievable, I've lost hours.Gnathic
C
2

This is a known problem... for workarounds see here and here.

Another option might be to

defaults write NSGlobalDomain NSExceptionHandlingMask 63

Although it is usually for OSX it might help when using the emulator - I can't try it right now though :-(

Claymore answered 14/11, 2011 at 13:3 Comment(2)
fwiw defaults write NSGlobalDomain NSExceptionHandlingMask 63 didn't work for me.Passover
Also, this is not available for the iOS SDK.Adjoin
A
1

I had the same issue, turning 'Compile for Thumb' back on worked for me. Note: I only turned it back on for the Debug configuration, for obvious reasons.

Anderegg answered 25/1, 2012 at 21:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.