大田农业网

首页 > 正文

iOS13 一次Crash定位 - 被释放的NSURL.host

www.pednoy.com2019-08-26

一年一度的iOS升级将为开发人员提供一些适应性工作,一些工作正常的代码可能会崩溃。本文讨论iOS13上CoreFoundation对象的内存管理问题。

在iOS 13 Beta版本中,手中出现了崩溃:

崩溃在方法中,然后它在内部崩溃,可能是由ObjC对象的传入野指针引起的。

通过跟踪源代码,我发现调用了这个方法,然后找到了这个方法的定义:

根据上下文,它是第二个参数wild指针。

然后找到这个对象的初始化:

这段代码似乎没有问题,它怎么能引起狂野指针,然后崩溃?

这是从iOS的内存管理中找到答案。

我们都知道Apple使用“引用计数”技术来管理内存,并使用“自动发布池AutoreleasePool”技术来解决方法返回值的内存管理问题。在线有很多关于相关技术原理的文章。但是,本文中遇到的崩溃是由Apple使用ARC代码进行编译优化引发的。那么让我谈谈这种优化是什么。

考虑最简单的内存管理情况:

2509688-bd5f9140e2fdfe33.png

在原始的ARC机制下,上图中左侧的代码将被编译到右侧的代码中,从而确保对象的生命周期完成。

但是让我们详细分析代码,是否可以删除代码和两个步骤,代码可以正常执行?答案是肯定的,然后可以优化此操作。 Apple已将此考虑在内。

那你怎么做这个优化?因为此优化需要同时考虑调用者:和调用者:一起工作,因为它依赖于调用者的内存管理代码来确定被调用者是否应该实际删除自动释放操作。并且还要在ABI上向下调整。 Apple这样做:

2509688-bef9e84dc725f25f.png

代码:

从上面的分析中,我们可以得出结论,只要看到调用指令,就可以明确地启用优化。

2509688-b608fb3dc8416b35.png

因此,在编译和调试时,您将看到这样一行指令。不要惊讶,你不这样做吗?它实际上用于优化。

在了解了ObjC的自动释放优化之后,回到我们遇到的崩溃问题。有理由怀疑此方法不会在旧系统上进行此优化,因此返回值会被放入,因此以后继续使用它是正常的。但iOS13进入了这个优化逻辑,并实际返回它没有添加。此时,没有objc对象接收,它直接传递给CF对象。这导致了直接释放。

通过查看对的调用代码来证明这个猜想:

2509688-f0073d775a6cfa6f.png

+312行呼叫获取主持人。

因为+316指令是如此,如果实现与上面类似,它将进入自动释放优化。也就是说,返回的主机没有加入autoreleasePool

在+320行中,由于启用了优化,因此也会捕获并保留

+328行,直接发布,这次主机发布

稍后继续访问它,只是崩溃。

还需要证明的是自身的实现。因此,比较iOS12和iOS13上的实现:

在iOS12上,内部调用,并添加了autoreleasePool。

2509688-4aa1515c18b1c9c2.png

在iOS 13上,执行自动释放是正常的,因此它将转到优化逻辑:

2509688-6c00aa51436ff300.png

请谨慎使用,以便在OC对象和CF对象之间进行直接转换。由于Autorelease优化的存在,这种用法可能会使您的代码不安全,因此尽可能多地使用转换和管理CF对象,避免由于范围不一致而提前释放对象的问题。

本文的来源是:

作者:Ji从淘宝iOS客户端架构组读取

淘宝基础平台团队正在招聘2019名实习生(2020年毕业)并招聘员工。这些职位包括iOS Android客户端开发工程师,Java研发工程师,C/C ++研发工程师,前端开发工程师和算法工程师。欢迎提交简历

如果您想了解有关淘宝基金会平台团队的更多信息,请观看团队介绍视频

作者:年纪

阅读原文

本文是云栖社区的原创内容,未经许可,不得转载。

热门浏览
热门排行榜
热门标签
日期归档