当用符号表示崩溃报告时,我注意到行号已关闭。我用一个我故意造成崩溃的项目对此进行了测试。生成的行号似乎不包括某些行,例如注释行或编译器预处理器语句(不确定它的作用和不包括什么)...
有没有一种简单的方法可以从符号崩溃报告中的“关闭”行号到源代码中的实际代码行?
编辑: 符号化崩溃报告中的一行示例:
7 Luisterpaal 0x00005de2 -[SWFMP3 connection:didReceiveData:] (SWFMP3.m:320)
所以,行号 320 几乎是正确的,但不完全正确。还差几行...
一句话……不。如果您在崩溃报告中看到这样的一行:
0 com.apple.CoreFoundation 0x95cb046b CFArrayAppendValue + 43
“+43”不是行号,而是函数开头的内存位置。您编写的代码根本不存在于已编译的二进制文件中 - 编译器会优化并更改代码(至少在发布版本中),因此它通常与您编写的内容不匹配。
不幸的是,解决方案是为遇到崩溃的人提供一个调试版本,您可以远程调试该版本,或者至少抛出 NSLog() 语句来帮助跟踪它,和/或编写更小的方法。
我也遇到了这个问题,但只是因为我正在查看比编译到崩溃的二进制文件中的代码更新版本的代码。当我返回源历史记录并找到源的相应版本时,行号完全匹配。
一个可能有帮助的建议 - 您可以使用
dwarfdump
命令检查 .dSYM
文件中的 DWARF 调试表,并确认它们与符号化崩溃报告的输出一致。
假设您在崩溃报告中看到代码地址
0x100024914
。请注意,这不是实际的内存地址,而是假设您的可执行文件加载到标准内存位置 0x100000000
的内存地址。出于安全原因,实际内存地址是随机的(通过添加一个称为“幻灯片”的随机值),但崩溃报告的堆栈跟踪中的代码地址已删除幻灯片。
现在你可以做:
dwarfdump my_program.dSYM --lookup=0x100024914
您将得到如下输出:
0x0001a9c3: Compile Unit: length = 0x00003367 version = 0x0004 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x0001dd2e)
0x0001a9ce: DW_TAG_compile_unit
DW_AT_producer ("Apple LLVM version 10.0.1 (clang-1001.0.46.4)")
DW_AT_language (DW_LANG_C99)
DW_AT_name ("./my_program.c")
DW_AT_stmt_list (0x0000f323)
DW_AT_comp_dir ("/Users/sim/my_program")
DW_AT_low_pc (0x0000000100020f70)
DW_AT_high_pc (0x0000000100025f58)
0x0001cb5f: DW_TAG_subprogram
DW_AT_low_pc (0x0000000100024070)
DW_AT_high_pc (0x0000000100024edb)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_name ("my_program_do_some_stuff")
DW_AT_decl_file ("/Users/sim/my_program/my_program.c")
DW_AT_decl_line (1165)
DW_AT_prototyped (true)
DW_AT_type (0x0001b8ae "my_result_t")
DW_AT_external (true)
0x0001cbe2: DW_TAG_lexical_block
DW_AT_low_pc (0x0000000100024117)
DW_AT_high_pc (0x0000000100024ec1)
Line info: file 'my_program.c', line 1333, column 22, start line 1165
现在,如果您确认
dwarfdump
中的行号与符号崩溃报告中的行号一致(我希望如此),这样您就知道崩溃符号引擎本身没有任何问题(Apple 的未记录的 CoreSymbolication
框架)——它正确输出可用的 DWARF 调试数据。如果错误的行号确实是由于错误造成的(而不只是开发人员的困惑,例如查看源文件的错误版本,如另一个答案中提到的),那么错误似乎必须存在于编译器中(有点不可能,但肯定以前没有发生过。)