如何找到程序崩溃的 “凶手” ?

本文详细解析了神策分析iOS SDK如何采集和处理NSException和Unix信号异常,以实现崩溃信息的全面收集。通过设置全局异常处理函数和信号处理函数,确保在程序崩溃时能捕获$AppCrashed事件,并补发$AppEnd事件,保持行为序列的完整性。
摘要由CSDN通过智能技术生成

图片

一、引言

在 iOS 应用程序开发过程中,我们难免会碰到因各种异常而导致应用程序崩溃的情况。

对于开发过程中遇到的崩溃,我们可以根据本地崩溃信息快速定位问题。但对于线上版本发生的一些崩溃情况,我们只能通过收集崩溃信息来分析具体的原因。虽然 Apple 提供了崩溃信息上报的功能,但是并非所有的用户都开启了该功能。因此,对于数据采集 SDK 来说,采集崩溃信息并上报是一项必不可少的功能。

下面针对神策分析 iOS SDK 崩溃采集模块进行解析,希望能够给大家提供一些参考。

二、崩溃类型

采集应用程序的崩溃信息,主要分为以下两种场景:

  • NSException 异常;

  • Unix 信号异常。

设计崩溃采集方案之前,我们不妨先认识一下 NSException 和 Unix 信号。

2.1 NSException

NSException[1] 是 Foundation 框架提供的一个类。用于封装一些异常信息,在需要的时候向外抛出。封装的异常信息包括异常名称、异常原因、调用堆栈。

@interface NSException : NSObject <NSCopying, NSSecureCoding> @property (readonly, copy) NSExceptionName name;@property (nullable, readonly, copy) NSString *reason;@property (readonly, copy) NSArray<NSString *> *callStackSymbols; @end

在 iOS 应用程序中,最常见的就是通过 @throw 抛出的异常,如图 2-1 所示:

图片

图 2-1 异常处理流程(图片来源于 Apple 开发者文档[2] )

比如常见的数组越界访问异常:

@throw [NSException exceptionWithName:@"NSRangeException" reason:@"index 2 beyond bounds [0 .. 1]" userInfo:nil];

运行程序会出现如下异常信息:​​​​​​​

Terminating app due to uncaught exception 'NSRangeException', reason: 'index 2 beyond bounds [0 .. 1]'terminating with uncaught exception of type NSException

2.2 Unix 信号

在 iOS 系统自动采集的崩溃日志中,经常可以看到类似下面的日志:​​​​​​​

Exception Type: EXC_BAD_ACCESS (SIGSEGV)Exception Subtype: KERNINVALIDADDRESS at 0x0000000001000010VM Region Info: 0x1000010is not in any region. Bytes before following region: 4283498480REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL UNUSED SPACE AT START TEXT 0000000100510000-0000000100514000 [16K] r-x/r-x SM=COW.app/EkuaibaoTermination Signal: Segmentation fault: 11Termination Reason: Namespace SIGNAl, Code 0xb Terminating Process: exc handler [21776]Triggered by Thread: 9

其中,Exception Type 中的两个字段 EXC_BAD_ACCESS 和 SIGSEGV 分别指 Mach 异常和 Unix 信号。

那什么是 Mach 异常和 Unix 信号呢?

Mach 是 macOS 和 iOS 操作系统的微内核,Mach 异常是最底层的内核级异常[3]。Mach 异常会被转换成相应的 Unix 信号,并传递给出错的线程。上述 Exception Type 中的 EXC_BAD_ACCESS 是 Mach 层的异常,被转换成了 Unix 信号 SIGSEGV,然后传递给出错的线程。之所以会将 Mach 异常转换成 Unix 信号,是为了兼容 POSIX 标准(SUS 规范)[4],这样一来,开发者即使不了解 Mach 内核也可以通过 Unix 信号的方式进行兼容开发。

Unix 信号的种类有很多,在 iOS 应用程序中,常见的 Unix 信号[5]有如下几种:

  • SIGILL:程序非法指令信号,通常是因为可执行文件本身出现错误,或者试图执行数据段。堆栈溢出时也有可能产生该信号;

  • SIGABRT:程序中止命令中止信号,调用 abort 函数时产生该信号;

  • SIGBUS

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值