在Xcode 4.2 / iOS 5下的控制台中没有异常堆栈跟踪?

时间:2011-11-11 21:13:54

标签: xcode4.2 ios5

在Xcode 3.x和iOS 4下,如果在模拟器中发出未处理的异常信号,则在控制台输出中会产生异常堆栈跟踪(类似于Java)。

当我在Xcode 4.2下的iOS 5中引发未处理的异常时,运行完全相同的应用程序代码时,不会发生堆栈跟踪。 (我确实弄清楚了如何设置异常断点,但这不会在控制台中产生回溯。)

这仅仅是我需要在某处创建的Xcode设置,还是Xcode 4 / iOS 5的“功能”?有没有办法恢复这一点功能?

更新

不幸的是,添加uncaughtExceptionHandler不起作用。这是处理程序:

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];
}                                               

(事实证明它已经存在,做Flurry的事情,所以我只是添加了堆栈跟踪。)

这是启用它的地方(只在声明处理程序的下面几行):

- (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; 

我设置断点使我能够检查两个检索到的处理程序值。第一个是nil,第二个是明显有效的地址。但是当抛出测试异常时,处理程序(在iOS 5模拟器中)永远不会得到控制。 (虽然当我在iOS 4.2模拟器上运行时,它确实可以控制。)

在iPhone上显然无法设置NSExceptionHandlingMask。先决条件ExceptionHandling.framework不可用。

更新2

这有效:

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;
}

3 个答案:

答案 0 :(得分:36)

这有效:

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;
}

对于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;
}

还在等待某种解释为什么默认转储不再起作用和/或为什么(甚至更严重)uncaughtExceptionHandler不起作用。但是,显然这个问题只影响模拟器。

更新

有人指出,如果你去产品 - >方案 - >编辑方案,选择“运行(调试)”,选择“诊断”选项卡,然后单击“日志异常”,这将恢复缺少的Xcode默认异常日志记录,可能(我还没有尝试过),不需要以上黑客攻击。

答案 1 :(得分:2)

这是一个已知问题...对于变通方法,请参阅herehere

另一种选择可能是

defaults write NSGlobalDomain NSExceptionHandlingMask 63

虽然它通常用于OSX,但在使用模拟器时可能有所帮助 - 我现在无法尝试: - (

答案 2 :(得分:1)

我遇到了同样的问题,将“Compile for Thumb”改回来为我工作。注意:出于显而易见的原因,我只重新打开了Debug配置。