weak底层实现原理

作者: T_guo | 来源:发表于2019-11-01 13:09 被阅读0次

一、weak基本用法

weak是弱引用,用weak来修饰、描述所引用对象的计数器并不会加1,而且weak会在引用对象被释放的时候自动置为nil,这也就避免了野指针访问坏内存而引起奔溃的情况,另外weak也可以解决循环引用。

拓展:为什么修饰代理使用weak而不是用assign?

assign可用来修饰基本数据类型,也可修饰OC的对象,但如果用assign修饰对象类型指向的是一个强指针,当指向的这个指针释放之后,它仍指向这块内存,必须要手动给置为nil,否则会产生野指针,如果还通过此指针操作那块内存,会导致EXC_BAD_ACCESS错误,调用了已经被释放的内存空间;而weak只能用来修饰OC对象,而且相比assign比较安全,如果指向的对象消失了,那么它会自动置为nil,不会导致野指针。

二、weak原理概括

  • weak表其实是一个哈希表,key是所指对象的指针,value是weak指针的地址数组。(value是数组的原因是:因为一个对象可能被多个弱引用指针指向)
  • Runtime维护了一张weak表,用来存储某个对象的所有的
    weak指针。
    weak原理实现过程三步骤
  1. 初始化开始时,会调用objc_initWeak函数,初始化新的weak指针指向对象的地址


    image.png

    2.紧接着,objc_initWeak函数里面会调用objc_storeWeak() 函数,objc_storeWeak() 函数的作用是用来更新指针的指向,创建弱引用表。


    image.png
    3.在最后会调用clearDeallocating函数。而clearDeallocating函数首先根据对象的地址获取weak指针地址的数组,然后紧接着遍历这个数组,将其中的数组开始置为nil,把这个entry从weak表中删除,最后一步清理对象的记录。
详细步骤
  1. 初始化开始时,会调用objc_initWeak函数,初始化新的weak指针指向对象的地址
    当我们初始化weak变量时,runtime会调用NSObject.mm中的objc_initWeak,而objc_initWeak函数里面的实现如下:
id objc_initWeak(id *location, id newObj) {
// 查看对象实例是否有效,无效对象直接导致指针释放
 if (!newObj) {
     *location = nil;
    return nil;
 }
 // 这里传递了三个 bool 数值
 // 使用 template 进行常量参数传递是为了优化性能
 return storeWeakfalse/*old*/, true/*new*/, true/*crash*/>
 (location, (objc_object*)newObj);
}

通过上面代码可以看出,objc_initWeak()函数首先判断指针指向的类对象是否有效,无效,直接返回;否则通过storeWeak()被注册为一个指向value的_weak对象

  1. objc_initWeak函数里面会调用objc_storeWeak() 函数,objc_storeWeak() 函数的作用是用来更新指针的指向,创建弱引用表。
  2. 在最后会调用clearDeallocating函数。而clearDeallocating函数首先根据对象的地址获取weak指针地址的数组,然后紧接着遍历这个数组,将其中的数组开始置为nil,把这个entry从weak表中删除,最后一步清理对象的记录。

三、当weak指向的对象被释放时,如何让weak指针置为nil的呢?

1、调用objc_release
2、因为对象的引用计数为0,所以执行dealloc
3、在dealloc中,调用了_objc_rootDealloc函数
4、在_objc_rootDealloc中,调用了object_dispose函数
5、调用objc_destructInstance
6、最后调用objc_clear_deallocating,详细过程如下:
a. 从weak表中获取废弃对象的地址为键值的记录
b. 将包含在记录中的所有附有 weak修饰符变量的地址,赋值为nil
c. 将weak表中该记录删除
d. 从引用计数表中删除废弃对象的地址为键值的记录

相关文章

  • iOS底层原理:weak的实现原理

    iOS底层原理:weak的实现原理iOS底层原理:weak的实现原理

  • iOS weak 底层实现原理(二):objc-weak 函数列

    前言 为了全面透彻的分析 weak 的实现原理,前面 iOS weak 底层实现原理(一):SideTable|s...

  • weak底层实现原理

    一、weak基本用法 weak是弱引用,用weak来修饰、描述所引用对象的计数器并不会加1,而且weak会在引用对...

  • weak 底层实现原理

    总结:weak 是Runtime维护了一个hash(哈希)表,用于存储指向某个对象的所有weak指针。weak表其...

  • weak底层实现原理

    前言 weak用于一些对象相互引用的时候,避免出现强强引用,对象不能被释放,出现内存泄露的问题。 weak 关键字...

  • weak底层实现原理

    一、weak 基本用法 weak 是弱引用,用 weak 来修饰、描述所引用对象的计数器并不会增加,而且 weak...

  • IOS基础知识-weak原理篇

    weak底层原理 首先需要看下weak编译后的实现,比如有如下代码: 在通过clang编译后,代码实现如下: 编译...

  • weak

    weak的底层实现weak 弱引用的实现方式

  • weak的底层实现原理?

    1.何为weak? weak 是oc中定义对象属性property时用于修饰对象属性的关键字。 2.weak有什么...

  • 问题:weak 底层实现原理

    weak基本用法 weak是弱引用,用weak描述修饰或者所引用对象的计数器不会加一,并且会在引用的对象被释放的时...

网友评论

    本文标题:weak底层实现原理

    本文链接:https://www.haomeiwen.com/subject/atufbctx.html