在Xcode调试程序时,程序出现bug崩溃后,偏偏在控制台显示的崩溃堆栈看不到具体的函数调用信息以及函数行号等,这怎么办?
貌似是iOS5.0开始做了某些修改,Xcode显示的崩溃信息里不打印方法名了
"First throw call stack"后面显示的全是十六进制的地址,根本无法定位到崩溃的代码,以前崩溃之后是会显示详细的调用的方法名等信息(Xcode 4.2 debug doesn't symbolicate stack call)
这种情况是不是有点耍流氓啊,就像是说:我生气了,但就是不告诉你为什么,哎!!!
那么对我们苦逼的程序员涞水,我们应该怎么办呢?
1. 我们主动抛出异常
定义一个异常捕获函数
void uncaughtExceptionHandler(NSException*exception){
NSLog(@"CRASH: %@", exception);
NSLog(@"Stack Trace: %@",[exception callStackSymbols]);
// Internal error reporting
}
在程序初始化的时候调用捕获方法:NSSetUncaughtExceptionHandler
-(BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
// Normal launch stuff
}
NSSetUncaughtExceptionHandler 就是告诉系统, 当发生异常时, 使用这个函数作为回调.
这样之后, 发生crash时, 就可以看到打印出的call stack
2. 分析堆栈
上面捕获的堆栈显示一部分信息,但是具体的代码行号没有显示,我们又该怎么办呢?
(1) 粗略分析
从上面我们看到类名、方法名(AppDelagate的menuTicketURL方法),然后根据后面的偏移量定位到大概的代码行
上面编译之后的代码偏移量是328,这里再次强调这不是行号,只是编译后的代码偏移量,但是基本上和字符数差不多,你可以通过一些文本工具,通过统计你的方法的字符偏移量大致的估计出错的行,一般误差在3~5行内。经过计算,所以是在311行的位置
(2) 笨办法:直接断点调试
既然都知道是在“menuTicketURL”方法崩溃了,直接在它的起始位置下断点调试,很方便就会定位到崩溃的代码位置
其实这也是最简便的方法
(3) atos符号化
比如解析上面的0x00000001000aa48c地址
xcrun atos -o StoreFinder.app.dSYM/Contents/Resources/DWARF/StoreFinder -arch arm64 -l 0x00000001000aa48c
PS: atos的执行很费时,需要耐性等待