美文网首页程序员iOS开发iOS Developer
解析iOS线上崩溃日志(crash Log)

解析iOS线上崩溃日志(crash Log)

作者: 伯牙呀 | 来源:发表于2017-03-20 17:50 被阅读737次

    1、错误类型

    开发中遇到应用崩溃是在所难免的,可以进行断点等一步一步的调试。但是APP上线之后也可能遇到一些bug,首先看一些这些线上app crash 信息:

    * Application received signal SIGSEGV
    * Application received signal SIGBUS
    * -[NSConcreteMapTable keyboardWillShow:]: unrecognized selector sent to instance
    * -[__NSArrayM objectAtIndex:]: index 4294967295 beyond bounds for empty array
    * -[JKArray objectAtIndex:]: index (0) beyond bounds (0)
    
    • SIGSEGV、SIGBUS 和第三个一般是因为访问已被释放的内存或者调用不存在的方法导致的,
    • 余下两个就是数组越界的问题了。

    这些我们都是知道的,然后来看看具体的log信息:

    Application received signal SIGSEGV unrecognized selector sent to instance

    红色框对应的是 :dSYM UUID
    黑色框对应的是:异常内存地址

    2、解析方法

    2.1、使用友盟错误分析工具

    友盟iOS错误分析功能说明

    友盟错误分析工具下载

    2.2、使用dSYM 文件解析

    <1> 什么是 dSYM 文件

    Xcode编译项目后,我们会看到一个同名的 dSYM 文件,dSYM 是保存 16 进制函数地址映射信息的中转文件,我们调试的 symbols 都会包含在这个文件中,并且每次编译项目的时候都会生成一个新的 dSYM 文件,位于 /Users/<用户名>/Library/Developer/Xcode/Archives 目录下,对于每一个发布版本我们都很有必要保存对应的 Archives 文件 ( AUTOMATICALLY SAVE THE DSYM FILES 这篇文章介绍了通过脚本每次编译后都自动保存 dSYM 文件)。

    <2> dSYM 文件有什么作用

    当我们软件 release 模式打包或上线后,不会像我们在 Xcode 中那样直观的看到用崩溃的错误,这个时候我们就需要分析 crash report 文件了,iOS 设备中会有日志文件保存我们每个应用出错的函数内存地址,通过 Xcode 的 Organizer 可以将 iOS 设备中的 DeviceLog 导出成 crash 文件,这个时候我们就可以通过出错的函数地址去查询 dSYM 文件中程序对应的函数名和文件名。大前提是我们需要有软件版本对应的 dSYM 文件,这也是为什么我们很有必要保存每个发布版本的 Archives 文件了。

    <3> 如何解析dSYM 文件

    打开terminal(终端),进行查找和解析,大致步骤如下:

    MacBook-Pro:~ myName$ cd /Users/<用户名>/Library/Developer/Xcode/Archives
    
    MacBook-Pro:Archives myName$ ls
    2015-09-07  2015-11-03  2016-01-20  2016-05-30  2016-12-05
    2015-09-11  2015-12-07  2016-03-01  2016-06-22  2016-12-13
    2015-09-12  2016-01-05  2016-05-11  2016-06-30  2017-01-11
    2015-09-14  2016-01-13  2016-05-12  2016-07-01  2017-03-11
    2015-09-29  2016-01-14  2016-05-18  2016-08-12  2017-03-13
    2015-11-02  2016-01-19  2016-05-23  2016-12-01
    
    MacBook-Pro:Archives myName$ cd 2017-03-13
    
    MacBook-Pro:2017-03-13 myName$ ls
    xxx 2017-3-13 下午11.58.xcarchive
    
    MacBook-Pro:2017-03-13 myName$ cd xxx\ 2017-3-13\ 下午11.58.xcarchive/
    
    MacBook-Pro:xxx 2017-3-13 下午11.58.xcarchive myName$ ls
    Info.plist  Products    SCMBlueprint    dSYMs
    
    MacBook-Pro:xxx 2017-3-13 下午11.58.xcarchive myName$ cd dSYMs/
    
    MacBook-Pro:dSYMs myName$ dwarfdump --uuid <项目名>.app.dSYM
    UUID: 45733B26-456D-31A1-177C-7E8DE4EF7C15 (armv7) xxx.app.dSYM/Contents/Resources/DWARF/xxx
    UUID: E46DBE29-9288-A32F-BC67-F7F4EA2149DF (arm64) xxx.app.dSYM/Contents/Resources/DWARF/xxx
    
    MacBook-Pro:dSYMs myName$ dwarfdump --lookup 0x1000e4d54 -arch arm64 xxx.app.dSYM
    
    ----------------------------------------------------------------------
     File: xxx.app.dSYM/Contents/Resources/DWARF/xxx (arm64)
    ----------------------------------------------------------------------
    Looking up address: 0x00000001000e4d54 in .debug_info... found!
    
    0x0016524b: Compile Unit: length = 0x00001843  version = 0x0002  abbr_offset = 0x00000000  addr_size = 0x08  (next CU at 0x00166a92)
    
    0x00165256: TAG_compile_unit [106] *
                 AT_producer( "Apple LLVM version 8.0.0 (clang-800.0.42.1)" )
                 AT_language( DW_LANG_ObjC )
                 AT_name( "/Users/myName/Desktop/app/xxx/MyView.m" )
                 AT_stmt_list( 0x0006b8d4 )
                 AT_comp_dir( "/Users/myName/Desktop/app/xxx" )
                 AT_APPLE_optimized( 0x01 )
                 AT_APPLE_major_runtime_vers( 0x02 )
                 AT_low_pc( 0x00000001000e3370 )
                 AT_high_pc( 0x00000001000e5d74 )
    
    0x00165da2:     TAG_subprogram [121] *
                     AT_low_pc( 0x00000001000e4ccc )
                     AT_high_pc( 0x00000001000e4d6c )
                     AT_frame_base( reg29 )
                     AT_object_pointer( {0x00165dc1} )
                     AT_name( "-[MyView showinView:]" )
                     AT_decl_file( "/Users/myName/Desktop/app/xxx/MyView.m" )
                     AT_decl_line( 99 )
                     AT_prototyped( 0x01 )
                     AT_APPLE_optimized( 0x01 )
    Line table dir : '/Users/myName/Desktop/app/xxx'
    Line table file: 'MyView.m' line 102, column 5 with start address 0x00000001000e4d48
    
    Looking up address: 0x00000001000e4d54 in .debug_frame... not found.
    

    1、进入 dSYMs 文件夹

    • 进入 Archives 文件夹:
    cd /Users/<用户名>/Library/Developer/Xcode/Archives
    
    • 查看 Archives 此文件夹下的列表:
    ls
    
    • 选择你要查找的文件夹进入:
    cd 2017-03-13
    
    • 查看 2017-03-13 此文件夹下的列表(列表下应该只有一个):
    ls
    
    • 继续进入 xcarchive
    cd xxx 2017-3-13 下午11.58.xcarchive
    
    • 继续进入 dSYMs 文件夹
    cd dSYMs
    

    2、查找 UUID
    查看 xx.app.dSYM 文件的 UUID:

    dwarfdump --uuid <项目名>.app.dSYM
    

    会自动输出 UUID,如下:

    UUID: 45733B26-456D-31A1-177C-7E8DE4EF7C15 (armv7) xxx.app.dSYM/Contents/Resources/DWARF/xxx
    UUID: E46DBE29-9288-A32F-BC67-F7F4EA2149DF (arm64) xxx.app.dSYM/Contents/Resources/DWARF/xxx
    

    注意:正常情况下,崩溃日志里面的 dSYM UUID(上面截图里红色框里) 一定会和此处输出的一个 UUID 一样,这样才能进行下一步查找,如果不一样你就是进错文件夹了(2017-03-13 文件夹),这里我在输出里面随意进行了一些修改。

    3、查找 crash Log 的异常内存地址
    根据崩溃日志里 异常内存地址arm64的信息进行查找:

    dwarfdump --lookup 0x1000e4d54 -arch arm64 <项目名>.app.dSYM
    

    输出的结果:

    ----------------------------------------------------------------------
     File: xxx.app.dSYM/Contents/Resources/DWARF/xxx (arm64)
    ----------------------------------------------------------------------
    Looking up address: 0x00000001000e4d54 in .debug_info... found!
    
    0x0016524b: Compile Unit: length = 0x00001843  version = 0x0002  abbr_offset = 0x00000000  addr_size = 0x08  (next CU at 0x00166a92)
    
    0x00165256: TAG_compile_unit [106] *
                 AT_producer( "Apple LLVM version 8.0.0 (clang-800.0.42.1)" )
                 AT_language( DW_LANG_ObjC )
                 AT_name( "/Users/myName/Desktop/app/xxx/MyView.m" )
                 AT_stmt_list( 0x0006b8d4 )
                 AT_comp_dir( "/Users/myName/Desktop/app/xxx" )
                 AT_APPLE_optimized( 0x01 )
                 AT_APPLE_major_runtime_vers( 0x02 )
                 AT_low_pc( 0x00000001000e3370 )
                 AT_high_pc( 0x00000001000e5d74 )
    
    0x00165da2:     TAG_subprogram [121] *
                     AT_low_pc( 0x00000001000e4ccc )
                     AT_high_pc( 0x00000001000e4d6c )
                     AT_frame_base( reg29 )
                     AT_object_pointer( {0x00165dc1} )
                     AT_name( "-[MyView showinView:]" )
                     AT_decl_file( "/Users/myName/Desktop/app/xxx/MyView.m" )
                     AT_decl_line( 99 )
                     AT_prototyped( 0x01 )
                     AT_APPLE_optimized( 0x01 )
    Line table dir : '/Users/myName/Desktop/app/xxx'
    Line table file: 'MyView.m' line 102, column 5 with start address 0x00000001000e4d48
    
    Looking up address: 0x00000001000e4d54 in .debug_frame... not found.
    

    看一下结果:发现有 AT_nameLine table dirLine table file,这样就找到了出错的地方(MyView showinView: 方法出错了)。

    注意:如果发现 warning: unsupported file type: 错误,这个问题是因为有文件或者目录的名称中包含空格,比如:2017-3-13/xxx 8-30-13 6.19 ,所以,需要转义一下:2017-3-13/xxx\ 8-30-13\ 6.19\ xxx.xcarchive。最好要cd进入下一级的名称从当前的ls列表复制过去。

    相关文章

      网友评论

        本文标题:解析iOS线上崩溃日志(crash Log)

        本文链接:https://www.haomeiwen.com/subject/wrqinttx.html