美文网首页
iOS Crash问题的捕获

iOS Crash问题的捕获

作者: ChenL | 来源:发表于2020-10-09 17:08 被阅读0次

    并不是所有的crash都可以捕获的NSException,如果捕获不到,可以使用signal机制来捕获Crash发生时的错误内容。

    一、可以捕获NSException,通过注册NSUncaughtExceptionHandler捕获异常信息

    //注册异常处理函数
    
    NSSetUncaughtExceptionHandler(&uncaught_exception_handler);
    
    //异常处理函数
    
    static void uncaught_exception_handler (NSException *exception) {
    
    //可以取到 NSException 信息
    
    //...
    
    abort();
    
    }
    
    

    注:使用OC的异常处理是不能得到signal的

    二、无法捕获的NSexception,利用Unix标准的signal机制,注册SIGABRT, SIGBUS, SIGSEGV等信号发生时的处理函数。

    /注册处理SIGSEGV信号
    
    signal(SIGSEGV,handleSignal);
    
    // 注册处理其他信号 ....
    
    //信号处理函数
    
    static void handleSignal( int sig ) {
    
    }
    

    三、异常信息解读

    1、Exception Type(异常类型)

    Exception Type:通常包含Signal信号 和 EXC_BAD_ACCESS,NSRangeException等。

    2、Exception Code(异常编码)

    Exception Code:以一些文字开头,紧接着是一个或多个十六进制值。这些数值说明了Crash发生的本质。

    从Exception Code中,可以区分出Crash是因为程序错误、非法内存访问还是其他原因。

    四、Crash日志符号化

    1、概述:

    线程回溯部分内容如下:

    2 AppName                         0x0000000100205280 0x0000000100028000 + 1954432
    
    3 AppName                         0x00000001002ae59c 0x0000000100028000 + 2647440
    

    这两条记录包括四列:(以第一条记录为例子)

    帧编号 2 (数字越小,发生时间越晚,发生顺序往后,越好锁定问题的范围)

    二进制库的名称 AppName

    调用方法的地址 0x0000000100205280

    一个基本地址 和 一个偏移量 0x0000000100028000 + 1954432 第一个数字指向文件,第二个数字指向文件中代码行

    说明1: 线程回溯部分并不是我们习惯使用方法名和行数,而是十六进制地址。所以我们在分析Crash前需要将这些十六进制地址转化成方法名称和行数,改过程被称为符号化

    说明2: 符号化crash日志需要获取对应的应用二进制文件以及生成二进制文件的.dsym文件(符号表)。必须完全匹配才行。否则,日志将无法被完全符号化。

    说明3: Xcode编译项目后,会得到同名的dsym文件(符号表),dsym文件(符号表)是保存16进制函数地址映射信息的中转文件,我们调试的symbols都会包含在这个文件中,并且每次编译项目的时候都会生成一个dsym文件,位于 /Users/<用户名>/Library/Developer/Xcode/Archives 目录下,对于每一个发布版本我们都很有必要保存对应的Archives文件。

    说明4:符号化可以使用Xcode的两种命令 symbolicatecrash命令 + atos命令

    2、symbolicatecrash命令

    1、首先找到symbolicatecrash命令

    find /Applications -name symbolicatecrash -type f
    

    我的本机命令的位置:
    /Applications/Xcode.app/Contents/SharedFrameworks/CCFoundation.framework/Versions/A/Resources/symbolicatecrash

    2、找到线上版本对应的xcarchive文件。从中找到.dsym 和 .app文件

    xcarchive所在的路径一般在: /Users/<用户名>/Library/Developer/Xcode/Archives 目录下

    3、获取crash日志文件

    线上App的crash日志由crash日志收集服务获取。
    也可以从真机上获取crash日志文件。点击window->devices,选择你自己的机器,然后点击 View Device Logs,右键可以导出crash文件。
    获取的这些日志文件都需要符号化处理。

    4、将symbolicatecrash、crash.crash、.dsym、.app拷贝到桌面下同一个文件夹下

    5、检查xxx.app 和 xxx.app.dsym文件以及crash文件这三种的UUID是否一致。

    查看 xxx.app 文件的 UUID,terminal 中输入命令 :

    dwarfdump --uuid xxx.app/xxx (xxx代表你的项目名)
    

    查看 xxx.app.dSYM 文件的 UUID ,在 terminal 中输入命令:

    dwarfdump --uuid xxx.app.dSYM
    

    查看crash 日志中的Incident Identifier (crash 文件的 UUID)

    6、使用命令,生成“可定位问题的crash文件”

    dwarfdump --uuid xxx.app.dSYM
    

    symbolreportXXX.crash就是符号化后的文件

    ./symbolicatecrash crashXXX.crash appName.app.dSYM > symbolreportXXX.crash

    7、根据符号化后的线程回溯信息,可以帮助定位问题的代码行。

    说明:如果执行symbolicatecrash命令出现 Error: "DEVELOPER_DIR" is not defined at ./symbolicatecrash...这样的错误,可以在执行命令前,输入export DEVELOPER_DIR="/Applications/XCode.app/Contents/Developer"

    3、atos命令

    在符号化时候,还可以使用atos命令。发现armv7 处理器上的crash使用 symbolicatecrash 无法符号化。

    1)将.dSYM、.app、crash.crash放到同一个文件夹下。

    2) 知道crash文件的UUID:执行grep "AppName arm" *crash,得到结果

    crash1.crash:0x100040000 - 0x100e23fff +AppName arm64 /var/containers/Bundle/Application/55A4D641-847F-4D24-86E1-129B28461858/AppName.app/AppName

    crash2.crash:0x100060000 - 0x100e43fff +AppName arm64 /var/containers/Bundle/Application/3229ED68-8D19-406D-A3F5-EC0310C9DB7C/QAppName.app/AppName

    crash3.crash: 0x5000 - 0xce8fff +AppName armv7 <7d62327effef37d384658020625a9944> /var/containers/Bundle/Application/C6BE271D-2EAC-42C0-8E72-4523F88C76B2/AppName.app/AppName

    其中0x100040000、0x100060000、0x5000是加载地址(loadingAddress), 而arm64、armv7 是 architecture 的值(architectureValue),这两个值后面都要用。

    3)然后执行atos命令,输入成功,进入待输入状态

    xcrun atos -o appName.app.dSYM/Contents/Resources/DWARF/appName -l loadingAddress -arch architectureValue

    4)此时输入App对应的crash地址,得到发生crash的信息

    实例1:

    grep "AppName arm" *crash

    xcrun atos -o AppName.app.dSYM/Contents/Resources/DWARF/AppName -l 0x100040000 -arch arm64

    实例2:

    grep "AppName arm" *crash

    xcrun atos -o AppName.app.dSYM/Contents/Resources/DWARF/AppName -l 0x5000 -arch armv7

    相关文章

      网友评论

          本文标题:iOS Crash问题的捕获

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