iOS开发中,经常遇到App在开发及测试时不会有问题,但是装在别人的设备中会出现各种不定时的莫名的 crash,因为iOS设备会保存应用的大部分的 crash Log,所以可以通过 crash Log 来定位 crash 原因。

一. 获取iOS设备上的 crash log

1. 将iOS设备连接到电脑上,打开 Xcode -> Organizer -> Devices,找到该台设备,在 Device logs 中找到 crash log(后缀为 .crash 的 log 文件),将其导出即可。

2. 如果你的应用已经上架App Store,那么开发者可以通过iTunes Connect(Manage Your Applications - View Details - Crash Reports)获取用户的crash log。不过这并不是100%有效的,而且大多数开发者并不依赖于此,因为这需要用户设备同意上传相关信息,详情可参见iOS: Providing Apple with diagnostics and usage information摘要。

二. 解析iOS crash log

获取到的 crash log 中的相关信息都是 16 进制的内存地址,并不能定位崩溃的代码,所以需要将 16 进制的内存地址解析为对应的类及方法。

解析 crash log 需要使用上传应用时所发送的 .app 及 .sYSM 两个文件(所以每次上传新版本时都要保存这两个文件,不然没法解析 crash log),可以将 .app .dYSM 及crash log文件拷贝到同一个文件夹下,使用 Symbolicatecrash 进行解析。

获取 .app 及 .dYSM 文件:在iOS开发中,需要使用Xcode打包生成 .xcarchiver 文件,可以在Xcode - > Organizer - > archive 中进行管理并导出相应的 .xcarchiver 文件,.xcarchiver 文件中就包含 .app 及 .dYSM 文件。

Symbolicatecrash 是一个隐藏文件,并且独立于Xcode,位置在:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash

在利用 Symbolicatecrash 进行解析之前,要检查 .app .dYSM 及 crash log 三个文件的uuid是否一样,只有三者都一样才能进行解析。查看三个文件的 uuid 方法如下:

1. 查看xx.app文件的uuid的方法,在 terminal.app 中输入:

$ dwarfdump --uuid xxx.app/xxx (xxx工程名)

2. 查看xx.app.dSYM文件的uuid的方法,在命令行输入:

$ dwarfdump --uuid xxx.app.dSYM (xxx工程名)

3. 查看 crash log 文件的 uuid的方法:

在 crash log 文件中,找到 Binary Images: 项目名后面第一个尖括号中的一串码就是改 crash log 文件的 uuid。

利用 Symbolicatecrash 进行解析:

在 terminal.app 中输入如下命令:

$ ./symbolicatecrash xxx.crash xxx.app.dSYM > test.log

该命令会将 crash 文件解析成 test.log 文件,test.log 就是可读的函数文件。

输入上述命令可能会出现Error: "DEVELOPER_DIR" is not defined at ./symbolicatecrash line 53.这个错误。

如果出现上述错误,输入命令:export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer,

然后继续执行./symbolicatecrash xxx.crash xxx.app.dSYM > test.log可以成功

三. 其他解析(根据地址解析):

解析某一个地址的内容

方法一:

$ xcrun atos -o xxx.app/xxx -arch armv7 0x38ad42f9 0x38ad42f9 0x38ad42f9(多个16进制地址,使用空格分开)

方法二:

$ dwarfdump -–lookup 0x000036d2 -–arch armv6 xxx.app.dSYM

如果根据以上两个方法操作,均提示找不到地址的话,可以使用方法三:

方法三:

查找以下内容所对应的地址:

(当前代码行地址 = 当前地址 + 地址偏移量,地址偏移量为十进制数值)

10  TestTransform                    0x00057132 0x4f000 + 33074

1. 先说第一种比较简单的方法利用 "当前地址" 和 "当前代码行地址"

$ xcrun atos -o TestTransform.app/TestTransform -arch armv7 0x3d000 0x0004fc5c

//输出结果:

bddeMacBook-Pro:1 baidu$ xcrun atos -o /Users/baidu/Desktop/1/TestTransform.app/TestTransform -l 0x3d000 0x0004fc5c

got symbolicator for /Users/baidu/Desktop/1/TestTransform.app/TestTransform, base address 4000

main (in TestTransform) (main.m:16)

2. 第二种相对复杂一点,涉及到地址的偏移,首先查看起始地址,即使每次iOS app启动都会加载(main module)主模块在不同的内存地址,但是dSYM文件假设你的main module加载在地址0x1000(大多数情况是这个,也有0x4000的)。

获取此地址的方法:

$ otool -arch armv7 -l /Users/cnstar-tech/crash/xxx.app/xxx  | grep -B 1 -A 10 "LC_SEGM" | grep -B 3 -A 8 "__TEXT"

调用以上方法返回结果如下:

Load command 1

cmd LC_SEGMENT

cmdsize 600

segname __TEXT

vmaddr 0x00004000

vmsize 0x00014000

fileoff 0

filesize 81920

maxprot 0x00000005

initprot 0x00000005

nsects 8

flags 0x0

看到vmaddr显示为0x00004000。

然后查看  "TestTransform 0x00057132 0x4f000 + 33074"  使用 起始地址+地址偏移量如:

0x4000 + 33074 = 0xc132   (注意:前面为前面为16进制后面为10进制相加,要都转换成10进制相加,把得出的结果转换成16进制)

就可以使用 "0xc132" 地址查看内容了:

//方法一:

$ dwarfdump --lookup 0xc132 --arch armv7 TestTransform.app.DSYM

//输出结果:

----------------------------------------------------------------------

File: TestTransform.app.DSYM/Contents/Resources/DWARF/TestTransform (armv7)

----------------------------------------------------------------------

Looking up address: 0x000000000000c132 in .debug_info... found!

0x00003947: Compile Unit: length = 0x00007b6e  version = 0x0002  abbr_offset = 0x00000000  addr_size = 0x04  (next CU at 0x0000b4b9)

0x00003952: TAG_compile_unit [1] *

AT_producer( "Apple LLVM version 5.1 (clang-503.0.38) (based on LLVM 3.4svn)" )

AT_language( DW_LANG_ObjC )

AT_name( "/Users/baidu/Desktop/TestTransform/TestTransform/ViewController.m" )

AT_low_pc( 0x0000a950 )

AT_stmt_list( 0x0000089f )

AT_comp_dir( "/Users/baidu/Desktop/TestTransform" )

AT_APPLE_major_runtime_vers( 0x02 )

0x00003c22:    TAG_subprogram [39] *

AT_name( "__29-[ViewController aaaaaaaaaa:]_block_invoke" )

AT_decl_file( "/Users/baidu/Desktop/TestTransform/TestTransform/ViewController.m" )

AT_decl_line( 191 )

AT_prototyped( 0x01 )

AT_APPLE_isa( 0x01 )

AT_accessibility( DW_ACCESS_public )

AT_low_pc( 0x0000c09c )

AT_high_pc( 0x0000c182 )

AT_frame_base( r7 )

0x00003c46:        TAG_lexical_block [34] *

AT_low_pc( 0x0000c0d6 )

AT_high_pc( 0x0000c17e )

Line table dir : '/Users/baidu/Desktop/TestTransform/TestTransform'

Line table file: 'ViewController.m' line 193, column 0 with start address 0x000000000000c11e

Looking up address: 0x000000000000c132 in .debug_frame... found!

0x00000160: FDE

length: 0x0000000c

CIE_pointer: 0x00000000

start_addr: 0x0000c09c __29-[ViewController aaaaaaaaaa:]_block_invoke

range_size: 0x000000e6 (end_addr = 0x0000c182)

Instructions: 0x0000c09c: CFA=4294967295+4294967295

//方法二:

$ xcrun atos -o /Users/baidu/Desktop/1/TestTransform.app/TestTransform 0xc132

//输出结果:

__29-[ViewController aaaaaaaaaa:]_block_invoke (in TestTransform) (ViewController.m:193)

四. 如何判断两个 crash log 文件的 crash 是同一个原因:

1. 可以先比较 Triggered by Thread 看看是否为同一个线程,不同,则不是同一原因。

2. 如果有 Last Exception Backtrace,可以先比较 Last Exception Backtrace 中地址的行数,行数不同则原因不同,行数如果相同可以将两个 Last Exception Backtrace 中的地址逐个进行比较,(一般最开始几行和最后几行都是调用系统函数,所以地址都是一样的),直到出现第一个不一样的地址,可以用 dwarfdump 分别解析两个地址,如果解析得到的方法不一样,则 crash 原因可不一样。

五. Xcode 中 Organizer 自动解析:

如果项目是在自己机器上打包的,可以将iOS设备连接到电脑上,这样该设备中的 crash log 就会被 Organizer 自动进行解析,如果没有自动解析,可以 右击 crash log 选择 re-symbolicate 进行解析。(之所以 Organizer 可以进行自动解析,是因为在打包的时候会建立 .app 及 .dYSM 两个文件的索引,所以可以自动解析 crash log 文件)

也可以进行手动建立索引,即将该 App 的 .app 及 .dYSM 两个文件拷贝到同一个文件夹中,然后再用 midimport foldername 命令进行手动建立索引,然后,将 crash log 文件导入 Xcode Organizer 中,就会进行自动解析。(可以批量导入 crash log 文件,批量进行解析)

六. 使用专门的 crash log 解析工具进行解析:

比如QuincyKit, Crashlytics, Flurry等。

iOS crash log 解析的更多相关文章

  1. iOS crash log 解析 symbol address = stack address - slide 运行时获取slide的api 利用dwarfdump从dsym文件中得到symbol

    概述: 为什么 crash log 内 Exception Backtrace 部分的地址(stack address)不能从 dsym 文件中查出对应的代码? 因为 ASLR(Address spa ...

  2. iOS: Crash文件解析(一)

    iOS Crash文件的解析(一) 开发程序的过程中不管我们已经如何小心,总是会在不经意间遇到程序闪退.脑补一下当你在一群人面前自信的拿着你的App做功能预演的时候,流畅的操作被无情地Crash打断. ...

  3. ios crash log

    1.IOS策略 1.1 低内存闪退 前面提到大多数crash日志都包含着执行线程的栈调用信息,但是低内存闪退日志除外,这里就先看看低内存闪退日志是什么样的.我们使用Xcode 5和iOS 7的设备模拟 ...

  4. ios Crash Log 分析汇总

    方法一: 1.xcode 有自带的symbolicatecrash,可以将.crash文件中的16进制地址转换成可读的函数地址. symbolicatecrash位于: /Applications/X ...

  5. AtoS查看iOS Crash log中的16进制代码日志

    注意:crash_log一定要和打包时的archive对应上: 方法1)在Orgnizer里找到某一个archive,即:/Users/handywang/Library/Developer/Xcod ...

  6. 别用symbolicatecrash来解析crash Log了

    今天突然发现了一个解析iOS crash log的好方法,忍不住来分享一下. 相信每个做iOS开发的TX都应该不会对symbolicatecrash陌生,我们第一次遇到真机上产生的崩溃日志时,在网上搜 ...

  7. 浅谈 iOS 之 Crash log 符号化

    其实,对于做移动 APP 开发的同学来说,质量和体验都是同等重要的.一个 APP 应用如果经常「闪退」,是产品质量很差的一个体现,那么用户体验就更不用再提了. *** 上面是笔者截取的国外一家公司对用 ...

  8. iOS Crash文件的解析

    iOS Crash文件的解析 开发程序的过程中不管我们已经如何小心,总是会在不经意间遇到程序闪退.脑补一下当你在一群人面前自信的拿着你的App做功能预演的时候,流畅的操作被无情地Crash打断.联想起 ...

  9. iOS 几种常用的 crash log 崩溃信息调试方法

    前言:crash log 对 定位崩溃问题 ,并且不容易复现,尤其是及时对appstore 上正在运营的 app 的迭代改进来说 非常重要. 1 crash两种情况 1.1 测试环境下 追踪bug 1 ...

随机推荐

  1. [php] phar

    build.php打包www目录: <?php class A{ public $a = 1; } $p = new Phar('test.phar',0,'test.phar'); $p-&g ...

  2. YottaChain主网全面上线预示商业应用的落地区块链云存储不一样的云

    Yottachain存储网12月24日平安夜全面启动,意味着全球首个可商用的区块链存储公链全面落地.对于数据存储来说,小到我们个人的照片文档,大到政企机构数据库资料,都是互联网生活中如影随形的标配. ...

  3. 父工程 pom版本

    <!-- 集中定义依赖版本号 --> <properties> <junit.version>4.12</junit.version> <spri ...

  4. 对logistic回归分析的两重认识

    logistic回归,回归给人的直观印象只是要求解一个模型的系数,然后可以预测某个变量的回归值.而logistic回归在应用中多了一层含义,它经常应用于分类中.第一重认识:logistic是给真正的回 ...

  5. python每日练习0730

    """ 1. 现有面包.热狗.番茄酱.芥末酱以及洋葱,数字显 示有多少种订购组合, 其中面包必订,0 不订,1 订,比如 10000,表示只订购面包 "&quo ...

  6. xcode7 添加个人账户 is not on any development teams

    XCODE7已经可以免费真机测试, 但添加个人账户后,显示 is not on any development teams , 解决办法: 点击 “-” 删除当前账户,退出XCODE重新打开再添加即可 ...

  7. win7连接无线网出现黄色感叹号怎么办?

    用win7连接无线网,出现黄色感叹号: 1.IP冲突,“网络中心”-“无线网属性”,手动改下IP,子网掩码,网关,DNS 2.360断网急救箱修复问题

  8. 【2019 Multi-University Training Contest 10】

    01: 02: 03:https://www.cnblogs.com/myx12345/p/11671692.html 04: 05:https://www.cnblogs.com/myx12345/ ...

  9. C# 调用delphi编写的dll

    技术实现 如何逐步实现动态库的加载,类型的匹配,动态链接库函数导出的定义,参考下面宏定义即可: #define LIBEXPORT_API extern "C" __declspe ...

  10. [CSP-S模拟测试]:Park(树上DP)

    题目描述 公园里有$n$个雕像,有$n-1$条道路分别连接其中两个雕像,任意两个雕像可以直接或间接相连.现在每个景点$i$聚集着$P_i$只鸽子,旅行家手里有$v$数量的面包屑. 一旦旅行家在雕像$i ...