降本增效工具系列(二):IOS 系统 Crash 日志分析实战
文章目录
- 一、前言
- 二、Crash 崩溃报告分析实战
- 三、常见 Exception Type
- 四、拓展阅读
一、前言
当应用程序在IOS
设备上崩溃(例如,闪退)时,一份“Crash崩溃报告”将在该设备上创建并存储起来。崩溃报告描述了应用程序是在何种条件下崩溃的,大部分情况下包含一份当前正在运行线程的完整堆栈跟踪。
如果设备就在身边,可以连接设备,打开Xcode - Window - Organizer
,在左侧面板中选择Device Logs
(可以选择具体设备的Device Logs
或者Library
下所有设备的Device Logs
),然后根据时间排序查看设备上的crash
日志。这是开发、测试阶段最经常采用的方式。
如果应用程序已经提交到App Store
发布,用户已经安装使用了,那么开发者可以 通过iTunes Connect
(Manage Your Applications - View Details - Crash Reports
)获取用户的crash
日志。不过这并不是100%有效的,而且大多数开发者并不依赖于此,因为这需要用户设备同意上传相关信息。
产生崩溃日志的原因
- 应用违反操作系统规则,包括在启动、恢复、挂起、退出时
watchdog
超时、用户强制退出和低内存终止等。- 应用中有
Bug
!
从多任务窗口中终止一个暂停的应用程序不会产生崩溃日志。Apple
官方认为一旦一个应用被暂停,它有资格被iOS
在任何时间终止,因此不会产生崩溃日志。
二、Crash 崩溃报告分析实战
在IOS
设置-隐私-分析与改进-分析数据中查找当前日期的应用崩溃日志mrcs-2021-08-31-091354.ips
,日志内容大致如下:
{"app_name":"mrcs","timestamp":"2021-08-31 09:13:54.00 +0800","app_version":"2.1.7","slice_uuid":"85fda4ca-6eae-3600-91c8-6fa83b827d7a","adam_id":0,"build_version":"9","platform":2,"bundleID":"com.*.*","share_with_app_devs":0,"is_first_party":0,"bug_type":"109","os_version":"iPhone OS 14.6 (18F72)","incident_id":"3ADDB9E3-657A-4ECC-B1B1-377A79F793BB","name":"mrcs"}
Incident Identifier: 3ADDB9E3-657A-4ECC-B1B1-377A79F793BB //崩溃报告的唯一标识符
CrashReporter Key: 7643d5953a8b0562ded233540a11c1beabbb8b58 //设备标识相对应的唯一键值(并非真正的设备的UDID,为保护隐私iOS6以后已无法获取)
Hardware Model: iPhone10,3 //发生Crash的设备类型
Process: mrcs [8968] //Crash的进程名称,通常都是我们的App的名字, []里面是当时进程的ID
Path: /private/var/containers/Bundle/Application/A09D22A5-324F-4686-964B-51AE831927B7/mrcs.app/mrcs //可执行程序在手机上的存储位置,注意路径是到x.app/x,x.app其实是作为一个Bundle的,真正的可执行文件其实是Bundle里面的x
Identifier: com.*.* //App的Indentifier,通常为“com.xxx.yyy”
Version: 9 (2.1.7) //App的版本号,由Info.plist中
Code Type: ARM-64 (Native) //App的CPU架构
Role: Foreground
Parent Process: launchd [1] //当前进程的父进程,由于iOS中App通常都是单进程的,一般父进程都是launchd
Coalition: com.*.ccmsm [421]Date/Time: 2021-08-31 09:13:53.8890 +0800 //Crash发生的时间
Launch Time: 2021-08-31 09:13:18.1164 +0800 //系统登陆时间
OS Version: iPhone OS 14.6 (18F72) //系统版本,括号内的数字代表的时Bulid号
Release Type: User
Baseband Version: 6.71.01
Report Version: 104Exception Type: EXC_CRASH (SIGABRT) //异常类型
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Triggered by Thread: 21Application Specific Information:
abort() called
...................................
Thread 21 name: Dispatch queue: com.facebook.react.ShadowQueue
Thread 21 Crashed:
//编号 二进制库名 调用方法的地址 基本地址 + 偏移
0 libsystem_kernel.dylib 0x00000001d73517b0 0x1d732a000 + 161712
1 libsystem_pthread.dylib 0x00000001f39dc9c0 0x1f39d2000 + 43456
2 libsystem_c.dylib 0x00000001b4243a44 0x1b41d0000 + 473668
3 mrcs 0x0000000102dd4e18 0x102c08000 + 1887768
4 mrcs 0x0000000102dd4d9c 0x102c08000 + 1887644
5 mrcs 0x0000000102ddd034 0x102c08000 + 1921076
6 mrcs 0x0000000102ddd0d0 0x102c08000 + 1921232
7 mrcs 0x0000000102ddd0d0 0x102c08000 + 1921232
8 mrcs 0x0000000102ddd0d0 0x102c08000 + 1921232
9 mrcs 0x0000000102ddd0d0 0x102c08000 + 1921232
10 mrcs 0x0000000102ddd0d0 0x102c08000 + 1921232
11 mrcs 0x0000000102dda324 0x102c08000 + 1909540
12 mrcs 0x0000000102dd8908 0x102c08000 + 1902856
13 mrcs 0x0000000102ddda4c 0x102c08000 + 1923660
14 mrcs 0x0000000102dd96e8 0x102c08000 + 1906408
15 mrcs 0x0000000102dd8908 0x102c08000 + 1902856
16 mrcs 0x0000000102ddda4c 0x102c08000 + 1923660
17 mrcs 0x0000000102dd96e8 0x102c08000 + 1906408
18 mrcs 0x0000000102dd8908 0x102c08000 + 1902856
19 mrcs 0x0000000102ddda4c 0x102c08000 + 1923660
20 mrcs 0x0000000102dd96e8 0x102c08000 + 1906408
21 mrcs 0x0000000102dd8908 0x102c08000 + 1902856
22 mrcs 0x0000000102dddf38 0x102c08000 + 1924920
23 mrcs 0x0000000102dd9e14 0x102c08000 + 1908244
24 mrcs 0x0000000102dd8908 0x102c08000 + 1902856
25 mrcs 0x0000000102ddb598 0x102c08000 + 1914264
26 mrcs 0x0000000102dd8908 0x102c08000 + 1902856
27 mrcs 0x0000000102dda940 0x102c08000 + 1911104
28 mrcs 0x0000000102dd8908 0x102c08000 + 1902856
29 mrcs 0x0000000102dda940 0x102c08000 + 1911104
30 mrcs 0x0000000102dd8908 0x102c08000 + 1902856
31 mrcs 0x0000000102ddb598 0x102c08000 + 1914264
32 mrcs 0x0000000102dd8908 0x102c08000 + 1902856
33 mrcs 0x0000000102dda940 0x102c08000 + 1911104
34 mrcs 0x0000000102dd8908 0x102c08000 + 1902856
35 mrcs 0x0000000102dda940 0x102c08000 + 1911104
36 mrcs 0x0000000102dd8908 0x102c08000 + 1902856
37 mrcs 0x0000000102dda940 0x102c08000 + 1911104
38 mrcs 0x0000000102dd8908 0x102c08000 + 1902856
39 mrcs 0x0000000102dda940 0x102c08000 + 1911104
40 mrcs 0x0000000102dd8908 0x102c08000 + 1902856
41 mrcs 0x0000000102ddb598 0x102c08000 + 1914264
42 mrcs 0x0000000102dd8908 0x102c08000 + 1902856
43 mrcs 0x0000000102dda940 0x102c08000 + 1911104
44 mrcs 0x0000000102dd8908 0x102c08000 + 1902856
45 mrcs 0x0000000102dda940 0x102c08000 + 1911104
46 mrcs 0x0000000102dd8908 0x102c08000 + 1902856
47 mrcs 0x0000000102dda940 0x102c08000 + 1911104
48 mrcs 0x0000000102dd8908 0x102c08000 + 1902856
49 mrcs 0x0000000102dda940 0x102c08000 + 1911104
50 mrcs 0x0000000102dd8908 0x102c08000 + 1902856
51 mrcs 0x0000000102dda940 0x102c08000 + 1911104
52 mrcs 0x0000000102dd8908 0x102c08000 + 1902856
53 mrcs 0x0000000102ddc09c 0x102c08000 + 1917084
54 mrcs 0x0000000102cfe104 0x102c08000 + 1007876
55 mrcs 0x0000000102cf2e10 0x102c08000 + 962064
56 mrcs 0x0000000102d0b800 0x102c08000 + 1062912
57 mrcs 0x0000000102d0f860 0x102c08000 + 1079392
58 mrcs 0x0000000102cd0efc 0x102c08000 + 823036
59 libdispatch.dylib 0x00000001ab2562b0 0x1ab1f6000 + 393904
60 libdispatch.dylib 0x00000001ab257298 0x1ab1f6000 + 397976
61 libdispatch.dylib 0x00000001ab233344 0x1ab1f6000 + 250692
62 libdispatch.dylib 0x00000001ab233e2c 0x1ab1f6000 + 253484
63 libdispatch.dylib 0x00000001ab23d66c 0x1ab1f6000 + 292460
64 libsystem_pthread.dylib 0x00000001f39dd5bc 0x1f39d2000 + 46524
65 libsystem_pthread.dylib 0x00000001f39e086c 0x1f39d2000 + 59500
Thread 22:
0 libsystem_pthread.dylib 0x00000001f39e0864 0x1f39d2000 + 59492
//Crash时发生时刻,线程的状态(寄存器中的值)
Thread 21 crashed with ARM Thread State (64-bit):x0: 0x0000000000000000 x1: 0x0000000000000000 x2: 0x0000000000000000 x3: 0x0000000000000000x4: 0x000000010378c20c x5: 0x000000016dc98930 x6: 0x000000000000000a x7: 0x0000000102dd7248x8: 0x000000016dc9f000 x9: 0xef6382e5d8fc5092 x10: 0x0000000000000002 x11: 0x00000000fffffffdx12: 0x0000010000000000 x13: 0x0000000000000000 x14: 0x0000000000000000 x15: 0x0000000000000000x16: 0x0000000000000148 x17: 0x0000000000000002 x18: 0x0000000000000000 x19: 0x0000000000000006x20: 0x0000000000006e4b x21: 0x000000016dc9f0e0 x22: 0x0000000000000000 x23: 0x0000000144f1ff80x24: 0x0000000000000002 x25: 0x0000000000000000 x26: 0x0000000000000002 x27: 0x0000000000000000x28: 0x0000000000000001 fp: 0x000000016dc98880 lr: 0x00000001f39dc9c0sp: 0x000000016dc98860 pc: 0x00000001d73517b0 cpsr: 0x40000000esr: 0x56000080 Address size fault
//Crash时刻App加载的所有库,其中第一行是Crash发生时我们App可执行文件的信息,可以看出为arm64,可执行文件包的uuid为c0f……cd65,解析Crash的时候dsym文件的uuid必须和这个一样才能完成Crash的符号化解析。
Binary Images:
0x102c08000 - 0x103933fff mrcs arm64 <85fda4ca6eae360091c86fa83b827d7a> /var/containers/Bundle/Application/A09D22A5-324F-4686-964B-51AE831927B7/mrcs.app/mrcs
0x103d60000 - 0x103dcbfff dyld arm64 <c5d2aaed4aeb3e18a5d2c8b681a2d6eb> /usr/lib/dyld
.....................
EOF
由以上崩溃报告内容可知,Thread *
表示发生Crash
的线程调用栈,从上到下分别代表调用顺序,最上面的一个表示抛出异常的位置,依次往下可以看到API
的调用顺序。重点由以下内容定位Crash异常类型、错误码、导致异常发生的线程。
Exception Type: EXC_CRASH (SIGABRT) //异常类型
Exception Codes: 0x0000000000000000, 0x0000000000000000 //异常类型代码
Exception Note: EXC_CORPSE_NOTIFY
Triggered by Thread: 21
有以上可知,线程21导致应用崩溃问题产生。
注意⚠️:包含堆栈跟踪的崩溃报告需要先进行符号化(symbolicated
)才可以进行分析。符号化的过程是将内存地址替换为便于阅读的函数名称和行号。如果通过Xcode
的Organizer
窗口获取崩溃日志,那么该报告将在几秒钟后自动进行符号化。否则需要将.crash
文件导入到Xcode
的Organizer
进行符号化。
三、常见 Exception Type
EXC_BAD_ACCESS
通常由于访问了不该访问的内存导致。一般EXC_BAD_ACCESS
后面的"()"还会带有补充信息。SIGSEGV
: 通常由于重复释放对象导致,这种类型在切换ARC
之后已经很少见到。当我们收到 SIGSEGV 信号时,可以往以下几个方面考虑:
- 访问无效内存地址,比如访问Zombie对象;
- 尝试往只读区域写数据;
- 引用空指针;
- 使用未初始化的指针;
- 栈溢出;
SIGABRT
: 收到Abort
信号退出,通常Foundation
库中的容器为了保护状态正常会做一些检测,例如插入null
到数组中等会遇到此类错误。SEGV
:(Segmentation Violation
),代表无效内存地址,比如空指针,未初始化指针,栈溢出等;SIGBUS
:总线错误,与SIGSEGV
不同的是,SIGSEGV
访问的是无效地址,而SIGBUS
访问的是有效地址,但总线访问异常(如地址对齐问题);SIGILL
:尝试执行非法指令,可能不被识别或者没有权限;EXC_BAD_INSTRUCTION
,此类异常通常由于线程执行非法指令导致;EXC_ARITHMETIC
,除零错误会抛出此类异常;SIGFPE
:Floating Point Error,数学计算相关问题(可能不限于浮点计算),比如除零操作;SIGPIPE
:管道另一端没有进程接收数据;
由以上分析内容可知,异常代码是SIGABRT
。通常, SIGABRT
异常是由于某个对象接收到未实现的消息引起的。 或者,简单来说,在某个对象上调用了不存在的方法。
这种情况一般不会发生,因为A对象调用了B方法,如果B方法不存在,编译器会报错。但是,如果你是使用selector
间接调用方法的,编译器则无法检测对象是否存在该方法了。
此外,比较常见的崩溃基本都源于代码bug
,比如数组越界、插空、多线程安全性、访问野指针、发送未实现的selector等。
四、拓展阅读
- 《ReactNative专栏》
降本增效工具系列(二):IOS 系统 Crash 日志分析实战相关推荐
- 苹果官方 Crash文件分析方法 (iOS系统Crash文件分析方法)
对于提交的苹果官方的app,在审核的时候会给我们一些crash文件,对于这些有用的文件,里面是关于我们的bug的一些信息,那么该如何去调试呢 第一步:在任意目录创建一个目录,用来调试crash,我这里 ...
- Windows2008系统安全日志分析
Windows2008系统安全日志分析 1.IPC连接成功后会生成一个事件ID为4624的安全事件,示例如下: 已成功登录帐户. 主题: 安全 ID: NULL SID ...
- 助力企业降本增效的利刃--固定资产盘点系统
受到疫情的影响,对于各企业来说,节约成本无疑是一场重头戏.越来越多的企业开始重视"降本增效".作为企业内部活动的重要组成部分,固定资产直接影响到企业整体资源的分配和布局.精准的固定 ...
- FFmpeg命令行工具系列二---转码流程及过滤器
一.概述 在FFmpeg命令行工具系列一中,对FFmpeg的命令行工具FFmpeg.exe进行了简单的介绍,并举出了几个简单的例子.在这一章中,将进行一次详细的介绍,主要是对转码过程和过滤器进行介绍. ...
- 【华为云技术分享】降本增效的背后:华为云瑶光数字化经营实战
引言:华为云瑶光(Alkaid)作为面向云.AI.5G时代的分布式云操作系统,承载未来"分布式.确定性.多维智慧"的云,致力于打造"极优.极简"的云上体验. 根 ...
- 【腾讯云原生降本增效大讲堂】Kubernetes云上资源的分析与优化
嘉宾 | 胡启明 出品 | CSDN云原生 2022年6月30日,中国信通院.腾讯云.FinOps产业标准工作组联合发起的<原动力x云原生正发声 降本增效大讲堂>系列直播活动第2讲如期举行 ...
- iOS Crash日志分析必备:符号化系统库方法
如果你有过分析iOS崩溃日志的经验,一定经常看到日志里出现很多<redacted>的字段.这篇文章就是帮助开发者将这些字段符号化为对应的系统库方法名. 如果你已经掌握了这方面的知识,就直接 ...
- iOS App崩溃日志分析
APP新版本上线之前,一般都会经过测试团队的反复测试,确认无bug后才会发布.发布那刻作为开发人员的你,估计欣喜若狂吧,自豪吧!!.发布后线上运行好长一段时间,均安然无恙,可突然有一天你们家CEO说, ...
- ulimit限制 新系统_graylog日志分析系统上手教程
日志分析系统可以实时收集.分析.监控日志并报警,当然也可以非实时的分析日志.splunk是功能强大且用起来最省心的,但是要收费,免费版有每天500M的限制,超过500M的日志就没法处理了.ELK系统是 ...
最新文章
- sqlalchemy根据表名动态创建model类
- ThinkPHP源码阅读1-------访问流程
- Hibernate Tomcat JNDI数据源配置(转)
- Linux服务部署常用命令--top、free、df、scp
- 容器学习 之 容器的网络类型(十二)
- python带通滤波_python中的fft带通滤波器
- 服务器文件夹同步到手机,本机文件夹同步到云服务器
- Dubbo的设计理念原来就藏在这三张图中
- 04 能够使用String类常用方法操纵字符串 0214
- ADO.Net之SqlConnection、 Sqlcommand的应用
- 【算法】LeetCode算法题-Length Of Last Word
- python调用百度地图画轨迹图_利用python和百度地图API实现数据地图标注的方法
- c语言知识点总完整版pdf,C语言知识点总结 重点版.pdf
- nginx “504 Gateway Time-out”错误
- EventBus Vuex?
- python 坐标轴单位标注_matlab坐标轴如何带单位标注?
- 微信小程序-地区选择伪五级联动(选择国,省,市,县,镇)
- c语言中FLT_DIG和DBL_DIG是什么意思
- [深度学习] 使用LSTM实现股票预测
- 内核线程卡死两例——sysrq运用简例
热门文章
- mockito教程_Mockito教程
- Android有文件读写权限,无法读写文件 open failed: EACCES (Permission denied) 获取设备唯一不变id 所有文件读写权限按钮无法打开
- 数学建模实验——贷款计算
- Java图片扫描仪_Java扫描仪useDelimiter()方法及示例
- windows服务器远程桌面(rdpclip.exe)的妙用
- 一个包含动态变量的短信模板设计分析
- 判定表与判定树的画法_判定表和判定树测试.ppt
- 迭代回顾会议 五个分区_使用回顾作为异议工具的5个技巧
- vue渲染函数h的使用
- Win10全选,选中一行快捷键