01.从一个面试题看TaggedPointer
前言
之前我们在WWDC20-runtime优化中有初步接触到了 TaggedPointer
。本文就讲结合一个面试题加深对它的理解。
一、 一个面试题
分析一下下面的代码会有什么问题
1.1 分析
乍一看本题考验的是多线程读写,很难想到和 TaggedPointer
有关。本题两处中的不同点是字符串的长度而已。而根据我们之前对 TaggedPointer
的了解,其中的 Payload
会用来存储数据。但是 Payload
的长度是有限的,过长的数据就无法完整保存进去。
所以,这里分析两处的指针类型是不同的。
1.2 断点调试
较短的字符串
这里发现指针类型为 NSTaggedPointerString
。明显是一个 TaggedPointer
。
较长的字符串
这里的指针类型为 __NSCFString
是一个普通的指针。
1.3 问题
在第二段代码运行中出现了野指针的崩溃。
1.4 思考
根据奔溃的现象,你可能会想到。 TaggedPointer
的 Retain
和 Release
难道和普通的有不同么?
二、 源码分析
在 OC 源码中找到:
进一步找到具体实现:
通过 Retain
的源码,我们可以看出,在判断是 TaggedPointer
之后就直接 return
了,没有进行任何操作。
那么 Release 呢?我们探索一下源码:
发现这里和 Retain
是一样的处理。
三、 问题分析
初步了解了 Retain 和 Release 对与 TaggedPointer
之后,我们就很容易理解上面的面试题所发生的现象了
TaggedPointer
的较短的字符串没有进行 Retain Release 所以多线程异步读写过程中没有出现野指针错误非
TaggedPointer
的较长的字符串,由于进行了多线程异步读写操作,不断的 Retain Release ,所以可能出现野指针错误。
总结
TaggedPointer
是用于特定类型的小对象的,并不是那些类型就都是TaggedPointer
。前提是Payload
要能够装得下。Retain
Release
对TaggedPointer
的特殊处理,也提高了TaggedPointer
的效率,同时在多线程场景下的安全性也比较高。
Last updated