一个递归调用引发的 “血案”

本文通过一个实际的iOS SDK崩溃案例,探讨了递归调用可能导致的栈溢出问题。在排查过程中,分析了线程、栈空间和内存布局,确认了递归深度超出系统限制导致的栈溢出崩溃。解决方案包括限制递归深度,以防止类似问题的发生。
摘要由CSDN通过智能技术生成

1. 前言

递归是指一种通过重复将问题分解为同类的子问题而解决问题的方法。在程序中,通过函数直接或间接的调用自身来进行递归。[1]

我们在设计递归程序时需要一个或多个边界条件,用于退出递归。当未满足边界条件时调用函数自身,达到边界条件时退出递归。

2. 问题

在日常开发过程中,我们往往会使用递归处理一些逻辑。例如:在神策分析 iOS SDK 中,会使用递归逻辑进行埋点数据的上传。

简化流程如图 2-1 所示:

 

图 2-1 埋点数据上传的流程图

在程序中,如果函数无限调用自身,最终会导致栈溢出崩溃。通过流程图可以看出,退出递归的边界条件是所有数据上传成功或者某次数据上传失败,因此不会造成无限递归。

但是,仍有客户反馈此处递归发生了崩溃。

3. 排查经过

3.1. 推测原因

客户提供的部分堆栈信息如下:

...

35  SensorsAnalyticsSDK             0x0000000105d8e584 __39-[SAEventTracker flushRecordsWithSize:]_block_invoke_2 + 189828 (SAEventTracker.m:158)

36  SensorsAnalyticsSDK             0x0000000105d8e424 __39-[SAEventTracker flushRecordsWithSize:]_block_invoke + 189476 (SAEventTracker.m:161)

37  SensorsAnalyticsSDK             0x0000000105d8a4a8 -[SAEventFlush flushEventRecords:completion:] + 173224 (SAEventFlush.m:187)

38  SensorsAnalyticsSDK             0x0000000105d8e228 -[SAEventTracker flushRecordsWithSize:] + 188968 (SAEventTracker.m:147)

39  SensorsAnalyticsSDK             0x0000000105d8e584 __39-[SAEventTracker flushRecordsWithSize:]_block_invoke_2 + 189828 (SAEventTracker.m:158)

40  SensorsAnalyticsSDK             0x0000000105d8e424 __39-[SAEventTracker flushRecordsWithSize:]_block_invoke + 189476 (SAEventTracker.m:161)

41  SensorsAnalyticsSDK             0x0000000105d8a4a8 -[SAEventFlush flushEventRecords:completion:] + 173224 (SAEventFlush.m:187)

42  SensorsAnalyticsSDK             0x0000000105d8e228 -[SAEventTracker flushRecordsWithSize:]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值