我在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)
感谢。
答案 0 :(得分:255)
我尝试的任何东西都无法修复此问题(尝试了两个编译器,两个调试器等) 升级XCode以进行iOS 5更新后,似乎没有堆栈跟踪。
但是,我找到了一种有效的解决方法 - 创建自己的异常处理程序(由于其他原因也很有用)。首先,创建一个处理错误并将其输出到控制台的函数(以及您想要用它做的任何其他事情):
void uncaughtExceptionHandler(NSException *exception) {
NSLog(@"CRASH: %@", exception);
NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
// Internal error reporting
}
接下来,将异常处理程序添加到您的app delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
// Normal launch stuff
}
就是这样!
如果这不起作用,那么只有两个可能的原因:
NSSetUncaughtExceptionHandler
电话(整个应用只能有一个处理程序)。例如,某些第三方库设置了自己的uncaughtExceptionHandler。因此,尝试将其设置在didFinishLaunchingWithOptions
函数的END(或选择性地禁用第三方库)。或者更好的是,在NSSetUncaughtExceptionHandler
上设置一个符号断点,以便快速查看谁在调用它。您可能想要做的是修改当前的而不是添加另一个。EXC_BAD_ACCESS
不是一个例外;感谢@Erik B的评论,如下所示)答案 1 :(得分:109)
添加异常断点(使用断点导航器底部的+)有一个有用的选项。这将在任何异常中中断(或者您可以设置条件)。我不知道这个选择在4.2中是否是新的,或者我是否最终注意到它试图解决丢失的符号问题。
一旦你点击这个断点,就可以像往常一样使用Debug Navigator导航调用堆栈,检查变量等。
如果你想要一个适合复制/粘贴的符号化调用堆栈,gdb backtrace可以从那里正常工作:
(gdb) bt
#0 0x01f84cf0 in objc_exception_throw ()
#1 0x019efced in -[NSObject doesNotRecognizeSelector:] ()
(等)
答案 2 :(得分:46)
调试器上有一个新功能。您可以在抛出异常时设置断点,并在那里停止执行,就像以前在4.0上发生一样。
在“断点导航器”上,添加“异常断点”,然后在选项弹出窗口中按“完成”。
这就是全部!
PS:在某些情况下,最好只针对Objective-C例外进行破解。
答案 3 :(得分:21)
这是另一个解决方案,不像以前那么优雅,但如果你没有添加异常断点或处理程序,它只能是一种方法。
当应用程序崩溃,并且您获得原始第一个抛出调用堆栈(以十六进制数字表示)时,键入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
(在这种情况下没有星号),并获得类似的输出。
使用此方法,您可以从throw堆栈的顶部(将有大约5-7个系统异常传播器)遍历到您的函数,这会导致崩溃,并确定准确的文件和代码行。
此外,为了类似的效果,您可以在终端中使用atos实用程序,只需键入:
atos -o path/to/AplicationBundle.app/Executable 0xAdress1 0xAdress2 0xAdress3 ...
并且您获得符号化堆栈跟踪(至少对于具有调试符号的函数)。
这种方法更为可取,因为您没有每个地址调用info line
,只需从控制台输出中复制地址并将其粘贴到终端。
答案 4 :(得分:9)
您可以添加例外断点(使用断点导航器底部的+)和添加操作 bt
(单击添加操作按钮,选择Debugger Command,在文本字段中输入“bt”。一旦抛出异常,这将显示堆栈跟踪。
答案 5 :(得分:6)
这是一个常见问题,而不是4.2中的堆栈跟踪。您可以尝试在LLDB和GDB之间进行交换,看看您是否获得了更好的结果。
在此处提交错误报告。
http://developer.apple.com/bugreporter/
编辑:
我相信如果你换回LLVM GCC 4.2,你就不会发现这种情况。您可能会丢失所需的功能。
答案 6 :(得分: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;
}
答案 7 :(得分:6)
在Xcode的调试控制台提示符下键入:
image lookup -a 0x1234
它会告诉你类似的东西:
Address: MyApp[0x00018eb0] (MyApp.__TEXT.__text + 91088)
Summary: MyApp`-[MyViewController viewDidAppear:] + 192 at MyViewController.m:202
答案 8 :(得分:1)
重新启用'Compile for Thumb'(调试配置)对我有用。