Xcode 4.2调试不表示堆栈调用


140

我在iOS 5模拟器/设备中进行Xcode 4.2调试时遇到问题。如预期的那样,以下代码崩溃:

NSArray *arr=[NSArray array];
[arr objectAtIndex:100];

在iOS 4中,我得到了有用的十六进制数字堆栈跟踪。但是在iOS 5中,它给了我:

*** First throw call stack:
(0x16b4052 0x1845d0a 0x16a0674 0x294c 0x6f89d6 0x6f98a6 0x708743 0x7091f8 0x7fcaa9 0x2257fa9 0x16881c5 0x15ed022 0x15eb90a 0x15eadb4 0x15eaccb 0x6f02a7 0x6faa93 0x2889 0x2805)

谢谢。

Answers:


256

我尝试过的任何方法都无法解决此问题(尝试了两个编译器,两个调试器等)。在为iOS 5更新升级XCode之后,似乎没有堆栈跟踪工作。

但是,我发现了一种有效的解决方法-创建自己的异常处理程序(由于其他原因,该处理程序也很有用)。首先,创建一个函数来处理错误并将其输出到控制台(以及您要对其进行处理的其他操作):

void uncaughtExceptionHandler(NSException *exception) {
    NSLog(@"CRASH: %@", exception);
    NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
    // Internal error reporting
}

接下来,将异常处理程序添加到您的应用程序委托中:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{   
    NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
    // Normal launch stuff
}

而已!

如果这不起作用,则只有两个可能的原因

  1. 某种情况正在覆盖您的NSSetUncaughtExceptionHandler呼叫(整个应用程序只能有一个处理程序)。例如,某些第三方库设置了自己的uncaughtExceptionHandler。因此,请尝试将其设置在didFinishLaunchingWithOptions函数的结尾(或有选择地禁用第三方库)。或者更好的是,设置一个符号断点NSSetUncaughtExceptionHandler来快速查看谁在调用它。您可能想要做的是修改当前的而不是添加另一个。
  2. 您实际上并没有遇到异常(例如,EXC_BAD_ACCESS不是异常;请记入下面的@Erik B的评论)

1
很高兴听到:)我发现将崩溃日志写入文件并提示用户在下次启动时提交它很有用(仅在发布模式下,以免妨碍调试)。这让我得到了很多错误报告……并且用户知道他们的问题已得到解决:)
Zane Claes

2
这似乎不起作用- uncaughtExceptionHandler永远不会调用例程。
热舔

1
您能否更详细地说明如何使用它?它似乎对我不起作用。
Danut Pralea 2011年

1
很难过的xCode不能为我们显示此内容。
Authman Apatira

1
非常感激!苹果没有在IDE中实现这种基本功能,这令人感到莫名其妙。
devios1 2013年

110

有一个添加异常断点的有用选项(使用“断点导航器”底部的+)。这将在任何异常时中断(或者您可以设置条件)。我不知道此选择是4.2中的新增功能,还是我最后才注意到它试图解决缺少的符号问题。

遇到此断点后,您可以像往常一样使用Debug Navigator来导航调用堆栈,检查变量等。

如果您确实希望使用适合复制/粘贴或类似操作的符号调用堆栈,则gdb backtrace从那里可以正常工作:

(gdb) bt
#0  0x01f84cf0 in objc_exception_throw ()
#1  0x019efced in -[NSObject doesNotRecognizeSelector:] ()

(等等)


3
到目前为止,这对我来说非常理想。调试器现在在崩溃的行上停止,无需回溯。
蒂姆(Tim)

1
这也完全适合我。非常感谢,如果没有这个断点,我会发疯……
William Denniss 2011年

+1起作用了。它没有给您这么好的错误消息来解释异常的原因,但这只是一个开始...
Nicu Surdu 2012年

你是我的HotD @WiseOldDuck。
Maverick12年

这为我恢复了预期的行为。注意:还记得在新项目上重新添加此断点!
MechEthan

46

调试器上有一项新功能。您可以在抛出异常时设置一个断点,并在该处停止执行,就像在4.0上曾经发生的那样。

在“断点导航器”上,添加“异常断点”,然后在选项弹出窗口上按“完成”。

就这样!

PS:在某些情况下,最好仅打破Objective-C异常。


绝对是我的解决方案。
bradgonesurfing 2011年

这是我的问题。我和一位同事共享同一个Xcode项目,我问他是否有问题,但不是。不同之处在于,他的项目违反了Objective-C异常(objc_exception_throw)
horseshoe7

您只是帮助找到了一个无法追踪的错误。非常感谢。我到处都在寻找这样的东西。
rjgonzo 2012年

1
这就像一个魅力!那正是我在寻找的东西,这比添加异常处理程序要好,因为添加断点可以使您正确地抛出异常,异常处理程序可以工作,但只为您提供一个思路。
im8bit 2012年

21

这是另一种解决方案,不像以前那样优雅,但是如果您不添加异常断点或处理程序,则这只是一种方法。
当应用程序崩溃时,您会得到原始的第一个throw调用堆栈(以十六进制数字表示),请在Xcode控制台中键入info line *hex(不要忘记使用星号和0x十六进制说明符),例如:

(gdb) info line *0x2658
Line 15 of "path/to/file/main.m" starts at address 0x25f2 <main+50>
and ends at 0x267e <main+190>.

如果您使用的是lldb,则可以键入image lookup -a hex(在这种情况下不带星号),并且您将获得类似的输出。

使用此方法,您可以从引发堆栈的抛出堆栈顶部(大约有5-7个系统异常传播者)遍历到导致崩溃的函数,并确定确切的文件和代码行。

另外,为达到类似效果,您可以在终端中使用atos实用程序,只需键入:

atos -o path/to/AplicationBundle.app/Executable 0xAdress1 0xAdress2 0xAdress3 ...

并且您得到符号化的堆栈跟踪(至少对于具有调试符号的函数而言)。此方法是更可取的,因为您不必每次调用地址info line,只需从控制台输出中复制地址并将其粘贴到终端中即可。


9

您可以添加一个异常断点(使用“断点导航器”底部的+)并将动作添加 bt到其中(单击“添加动作”按钮,选择“调试器命令”,在文本字段中输入“ bt”)。一旦引发异常,这将显示堆栈跟踪。


6

这是一个常见问题,没有在4.2中获得堆栈跟踪。您可以尝试在LLDB和GDB之间交换以查看是否获得更好的结果。

在此处提交错误报告。

http://developer.apple.com/bugreporter/

编辑:

我相信,如果您交换回LLVM GCC 4.2,您将不会看到这种情况。但是,您可能会失去所需的功能。


是的,我尝试过切换编译器,但是问题仍然存在。但无论如何
还是

他建议切换调试器,而不是编译器。
bames53 2011年

1
仅供参考:在这种情况下,它与您使用的编译器或调试器的版本无关。这是iOS控制台输出中的更改。
clarkcox3 2011年

有趣的是,这种体验有多少变化-我认为有一些问题。我无法使调试器在异常断点处停止。从GDB切换到LLDB解决了该问题。
马特

6

在您的主要功能中使用以下代码:

int main(int argc, char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    int retVal;
    @try {
        retVal = UIApplicationMain(argc, argv, nil, nil);
    }
    @catch (NSException *exception) {
        NSLog(@"CRASH: %@", exception);
        NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
    }
    @finally {
        [pool release];
    }
    return retVal;
}

这似乎不适用于情节提要。2012-06-04 20:34:52.211问题[1944:207]如果应用程序委托要使用主故事板文件,则必须实现window属性。2012-06-04 20:34:52.213 Problems [1944:207]预计应用程序在应用程序启动结束时将具有根视图控制器
macasas 2012年

6

在Xcode的调试控制台提示符下,键入:

image lookup -a 0x1234

它将显示以下内容:

  Address: MyApp[0x00018eb0] (MyApp.__TEXT.__text + 91088)
  Summary: MyApp`-[MyViewController viewDidAppear:] + 192 at MyViewController.m:202

谢谢,我真的在找这个。令人惊讶的是,没有将整个“第一个throw调用栈”显示为调用栈的捷径,因为我猜想Python lldb脚本很容易编写。
伊利亚2015年

1

重新启用“为Thumb编译”(​​调试配置)对我来说很有效。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.