swift进阶七:引用计数(Strong、Unowned、Weak)

swift进阶 学习大纲

上一节,介绍了方法调度 & @objc & 指针。本节,我们就探究较难的引用计数,将从以下4个方面探索:

  1. Swift三大引用计数(strong、unowned、weak)
  2. 强引用 & 无主引用
  3. CFGetRetainCount计数统计
  4. 弱引用

swift中的引用计数OC一致,都是采用ARC(自动引用计数)管理。

OC的对象都是以objc_object为模板创建,其中首元素isa

  • 开启指针优化(nonpointer): 在isa存储引用计数,可使用散列表进行拓展存储
  • 未开启指针优化: 直接使用散列表进行存储
  • swift引用计数:
  • swift对象都是以HeapObject为模板创建,其中HeapObject的模板中第二个元素,是refCount引用计数属性,该属性记录了strong(强引用计数)和unowned(弱引用计数)等信息。
  • weak修饰对象,会另外生成WeakReference对象,内部HeapObjectSideTableEntry散列表类在原heapObject类的基础上,重新记录了refCount(管理strongunowned引用计数)并新增了weakBits弱引用计数。

1. Swift三大引用计数(strong、unowned、weak)

首先,我们先通过案例,体验一下Swift对象的三种引用类型:

  • strong(默认强引用类型)、unowned(无主引用类型)、weak(弱引用类型)
image.png
  1. 不管是哪种引用持有的都是原对象(从p到p5内存地址可以看出)
  2. 在每一行执行完后,x/4g打印p对象内存信息,在第二地址上,可以清晰感受到,强引用无主引用引用计数有规律增加,而弱引用没有变化
  • 经过了上面的初体验,我们对强引用无主引用计数的位置有了初步的感受,但弱引用的信息存放不明朗
  • 下面,我们通过案例SIL中间代码Swift源码汇编等方式,一点点揭开他们的面纱😃

2. 强引用 & 无主引用

2.1 源码探索

  • 当前以默认initialized方式进行初始化,分析HeapObject对象引用计数
  • swift源码探索过程:
    image.png
  • refCount内存布局
    image.png
  • 现在,我们知道强引用无主引用是在Uint64_t 8位refCount的不同位置。

2.2 引用计数分析

下面通过案例检查一下:

  • 创建一个Swift命令行项目
class HTPerson {
    var age  = 10
    var name = "ht"
}

var t = HTPerson()
var t1 = t
var t2 = t
print("end")
  • 【尝试一】: 在t1处断点t对象强引用无主引用计数都为1
image.png
  • 【尝试二】: 在t2处断点t对象强引用计数2无主引用计数1
image.png

2.3 强引用计数+1

  • 还是以上面测试代码为例,我们结合SIL中间代码和Swift源码分析:

【情况一】仅创建对象,默认强引用计数1

image.png

【情况二】进行一次引用强引用计数2SIL中可以看到copy_addr汇编可以看到使用swift_retain,在swift源码中可以知道执行路径为:

swift_retain->refCounts.increment(1)->incrementStrongExtraRefCount->强引用计数+1

image.png

3. CFGetRetainCount计数统计

  • CFGetRetainCount会在执行前,对对象进行strong_retain操作,在执行后,完成release_value操作。
    所以swiftCFGetRetainCount打印的强引用计数比原引用计数多1

注意:swift中,在lldbp打印内存,会引用计数+1,影响影响CFGetRetainCount结果
(断点,p打印一次或多次,x/4g在内存信息中可看到引用计数明显变化)

【情况一】不打印,无retain和release

image.png

【情况二】打印一次CFGetRetainCount,执行前strong_retain +1,执行完release_value -1

image.png

4. 弱引用

  • 我们知道swift是使用ARC(自动引用计数管理)的。如果产生循环引用,我们必须有弱引用机制去打破循环

swift中的弱引用,使用weak修饰。与OC不同的是:

  • OC:
    弱引用计数是存放在全局维护散列表中,isa中会记录是否使用了散列表
    引用计数0时,自动触发dealloc,会检查清空当前对象散列表计数

  • swift:
    弱引用计数也是存放在散列表中,但这个散列表不是全局的。

    • 如果对象没有使用weak弱引用,就是单纯的HeapObject对象,没有散列表
    • 如果使用weak弱引用,会变为WeakReference对象。这是一个Optionl(可空对象)。其结构中自带散列表计数区域。
      swift散列表refCount无关联。当强引用计数0时,不会触发散列表的清空。而是在下次访问发现当前对象不存在(为nil)时,会清空散列表计数

下面,我们通过案例源码来分析swift弱引用WeakReference对象内存结构

案例:

  • 可以发现:
    weak修饰前,p对象是HeapObject类型,可从refCount中看出强引用计数无主引用计数
    weak修饰后,p对象的类型变了

    image.png

  • 可以看到weak修饰p1对象,变成了optinal可选值
    (不难理解,weak修饰对象改变原对象的引用计数,只是一层可空状态

    image.png

  • 断点汇编可以看到swift_weakInit初始化,swift_weakDestroy释放。

    image.png

  • 进入swift源码,搜索swift_weakInit

image.png
  • 常规对象弱引用对象区别:
image.png
  • 现在,我们已知道弱引用实际上是WeakReference对象,信息都存储在side弱引用表中,可仿照getSideTable函数左移3位得到side散列表地址。读取弱引用信息

我们回到上面案例

image.png

  • 了解结构后,关于弱引用引用计数+1-1释放都在WeakReference类中有介绍,可以自行了解。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,816评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,729评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,300评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,780评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,890评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,084评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,151评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,912评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,355评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,666评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,809评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,504评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,150评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,121评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,628评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,724评论 2 351

推荐阅读更多精彩内容