iOS端崩溃问题定位总结

前言

崩溃问题修复是每一个客户端开发者治理的重难点,一般崩溃有三道程序监防:1、程序员代码编程规范化及Codereview ;2、程序员自测及测试部门同事测试;3、线上检测工具bugly、Firebase监测。崩溃修复是一个长期复杂的过程,程序员治理优化程序的过程中,同时也是提高自身能力和了解更广泛知识的过程。要想解决崩溃,首先就要学会定位线上崩溃问题,本文就总结分享了开发中定位崩溃问题的几种方法和大家做个分享。

崩溃问题定位

最重要的三个文件

  1. dSYM
  2. .crash / .ips 文件
  3. .app

并将三文件整理在一个文件夹中
流程:准备三文件 - > 符号化 -> 生成可直观的文件

dSYM文件获取

dSYM 是保存 16 进制函数地址映射信息的中转文件,我们调试的 symbols 都会包含在这个文件中,并且每次编译项目的时候都会生成一个新的 dSYM 文件,位于 /Users/<用户名>/Library/Developer/Xcode/Archives 目录下

一般开发者在完成一个版本后,就要迁出一个版本出来。选择真机或选择generic iOS Device, Product -> Archive,随后

XCode -> Window ->Organizer -> XXArchive文件 -> Show in Finder -> 显示包内容 -> dSYMs -> ***.app.dSYM

一般使用bugly线上监测,还应把该文件上传到bugly上帮助定位问题,上传脚本如下:
dsym文件和bugly文件放在同一路径下
java -jar buglyqq-upload-symbol.jar -appid *** -appkey **** -bundleid com...* -version 3.. -platform IOS -inputSymbol ..dSYM

若想上传app内引用的其他库的符号表,以方便查找是不是三方库的原因,可把..dSYM 替换成对应的三方库dsym,如:***.framework.dSYM 即可</pre>

|

.app文件获取

XCode -> Window ->Organizer -> XXArchive文件 -> Show in Finder -> 显示包内容 ->Products -> Applications -> *.app

.crash文件获取

1)手机连接Mac获取

XCode -> Window ->Devices and simulators -> view Device Logs
搜索你app的名称,即可找到真机产生的crash。

2)参与TestFight与上线共享crash

崩溃时可以直观的在XCode查看crash的代码行。

设备设置: 设置 -> 隐私 -> 与应用开发者共享。
获取报告:iTunes Connect ->Manage Your Applications -> View Details -> Crash Reports。导出即可。

定位方法

1、通过.dSYM符号表手动分析定位

下面是报错的堆栈信息:

10 **** 0x00000001052119b4 0x0000000104cd4000 + 5495220

如何分析出第7行的地址指向哪个方法呢?

终端执行如下指令

|

atos -arch arm64 -o ***.app.dSYM/Contents/Resources/DWARF/*** -l 0x0000000104cd40000x0000000105212c48

|

arm64:cpu架构,发生报错的APP的手机的cpu架构,可以通过手机型号去查询确认。

.app.dSYM/Contents/Resources/DWARF/:其中是APP的名字,导出符号表默认的,后面的路径是固定的,只要将替换成你的APP名字即可。(需要 cd 到符号表的文件目录下)

0x0000000104cd4000 + 5499976:0x0000000104cd4000表示默认Slide Address,5499976表示偏移量。

0x0000000105212c48:表示错误信息内存地址。

注意这两个地址的先后顺序。

执行结果如下:

|

MacBook`` test % atos -arch arm64 -o ***.app.dSYM/Contents/Resources/DWARF/*** -l 0x0000000104cd4000 0x0000000105212c48
-[take hold:] (socket:686)

|

得出-[socket onSocket:didReadData:withTag:]代码位置。

分析辅助工具

dSYM分析工具可以帮助定位

https://github.com/answer-huang/dSYMTools

[图片上传失败...(image-2f1457-1684396669921)]

2、通过hooper 反汇编定位

当发生Unix 信号的崩溃时不好定位问题,可借助hooper反编译来定位

10 *** 0x00000001052119b4 0x0000000104cd4000 + 5495220

由于是线上的崩溃,在拿到 xxx.xcarchive 包之后,把包里面的二进制文件拖进 hopper ,选择 Arm64 架构。接下来我们就可以分析跳转到具体的崩溃位置了,刚好崩溃的线程有包含我们的项目代码;

0x0000000104cd4000 是项目的基地址,5499976 是十进制的偏移量,而这个 0x0000000105212c48 则是崩溃地址,刚好是 0x0000000104cd4000 + 5499976 的结果。

所以,我们下面要做的就是跳转到 0x0000000105212c48 这个崩溃地址看看响应的汇编代码。

  1. hopper -> Modify -> Change File Base Address... ,然后把基地址 0x0000000104cd4000 输入,重新 Rebase 一下。

  2. hopper -> Navigate -> Go to Address or Symbol... ,输入 0x0000000105212c48 这个地址,然后 go 到对应的崩溃地址

通过上述步骤可以定位大概代码位置,然后根据业务推断问题出错点,再结合修改即可了。

常见崩溃问题

1)Mach 异常

最底层的内核级异常。用户态的开发者可以直接通过Mach API设置thread,task,host的异常端口,来捕获Mach异常。

新建一个监控线程,在监控线程中监听 Mach 异常并处理异常信息。主要的步奏如下图:

2)Unix信号

又称BSD 信号,如果开发者没有捕获Mach异常,则会被host层的方法ux_exception()将异常转换为对应的UNIX信号,并通过方法threadsignal()将信号投递到出错线程。可以通过方法signal(x, SignalHandler)来捕获signal。

Unix Signal 其实是由 Mach port 抛出的信号转化的,大致信号:

  • SIGHUP
    本信号在用户终端连接(正常或非正常)结束时发出, 通常是在终端的控制进程结束时, 通知同一session内的各个作业, 这时它们与控制终端不再关联。

  • SIGINT
    程序终止(interrupt)信号, 在用户键入INTR字符(通常是Ctrl-C)时发出,用于通知前台进程组终止进程。

  • SIGQUIT
    和SIGINT类似, 但由QUIT字符(通常是Ctrl-)来控制. 进程在因收到SIGQUIT退出时会产生core文件, 在这个意义上类似于一个程序错误信号。

  • SIGABRT
    调用abort函数生成的信号。
    SIGABRT is a BSD signal sent by an application to itself when an NSException or obj_exception_throw is not caught.

  • SIGBUS
    非法地址, 包括内存地址对齐(alignment)出错。比如访问一个四个字长的整数, 但其地址不是4的倍数。它与SIGSEGV的区别在于后者是由于对合法存储地址的非法访问触发的(如访问不属于自己存储空间或只读存储空间)。

  • SIGFPE
    在发生致命的算术运算错误时发出. 不仅包括浮点运算错误, 还包括溢出及除数为0等其它所有的算术的错误。

  • SIGKILL
    用来立即结束程序的运行. 本信号不能被阻塞、处理和忽略。如果管理员发现某个进程终止不了,可尝试发送这个信号。

  • SIGSEGV
    试图访问未分配给自己的内存, 或试图往没有写权限的内存地址写数据.

  • SIGPIPE
    管道破裂。这个信号通常在进程间通信产生,比如采用FIFO(管道)通信的两个进程,读管道没打开或者意外终止就往管道写,写进程会收到SIGPIPE信号。

  • SIGSYS

    非法的系统调用。

  • SIGTRAP

    由断点指令或其它 trap 指令产生. 由d ebugger 使用。

  • SIGILL

    执行了非法指令. 通常是因为可执行文件本身出现错误, 或者试图执行数据段. 堆栈溢出时也有可能产生这个信号。

3)应用级NSException

应用级异常,它是未被捕获的Objective-C异常,导致程序向自身发送了SIGABRT信号而崩溃,是app自己可控的,对于未捕获的Objective-C异常,是可以通过try catch来捕获的,或者通过NSSetUncaughtExceptionHandler()机制来捕获。

  • 非主线程刷新UI

  • NSInvalidArgumentException
    非法参数异常(NSInvalidArgumentException)是 Objective – C 代码最常出现的错误,所以平时在写代码的时候,需要多加注意,加强对参数的检查,避免传入非法参数导致异常,其中尤以nil参数为甚。

  • NSRangeException
    越界异常(NSRangeException)也是比较常出现的异常。

  • NSGenericException
    NSGenericException这个异常最容易出现在foreach操作中,在for in循环中如果修改所遍历的数组,无论你是add或remove,都会出错 “for in”,它的内部遍历使用了类似 Iterator进行迭代遍历,一旦元素变动,之前的元素全部被失效,所以在foreach的循环当中,最好不要去进行元素的修改动作,若需要修改,循环改为for遍历,由于内部机制不同,不会产生修改后结果失效的问题。

  • NSInternalInconsistencyException
    不一致导致出现的异常
    比如NSDictionary当做NSMutableDictionary来使用,从他们内部的机理来说,就会产生一些错误
    NSMutableDictionary *info = method return to NSDictionary type;
    [info setObject:@“sxm” forKey:@”name”];
    比如xib界面使用或者约束设置不当

  • NSFileHandleOperationException
    处理文件时的一些异常,最常见的还是存储空间不足的问题,比如应用频繁的保存文档,缓存资料或者处理比较大的数据:
    所以在文件处理里,需要考虑到手机存储空间的问题。

  • NSMallocException
    这也是内存不足的问题,无法分配足够的内存空间
    此外还有

  • KVO Crash
    移除未注册的观察者
    重复移除观察者
    添加了观察者但是没有实现-observeValueForKeyPath:ofObject:change:context:方法
    添加移除keypath=nil
    添加移除observer=nil

  • unrecognized selector send to instance

总结

本文也只是对崩溃问题做了浅显的总结和解决经验的分享,崩溃治理是开发者长期处理的过程,不仅要解决现有问题,还要防范崩溃问题出现并且做好兜底策略;在治理过程中对个人底层知识理解也有较大帮助。

参考:

https://juejin.cn/post/6937619147505270820

https://www.jianshu.com/p/3f6775c02257

https://www.cnblogs.com/ciml/p/7422872.html

https://zhuanlan.zhihu.com/p/420032439

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335

推荐阅读更多精彩内容