iOS - weak 底层原理

高分请问下,iOS - weak 底层原理
最新回答
失约

2024-10-24 08:17:29

[toc]

weak

https://blog.csdn.net/future_one/article/details/81606895

https://www.cnblogs.com/guohai-stronger/p/10161870.html

https://www.jianshu.com/p/2b12666b351f

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

weak也可以解决循环引用。

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

而 weak 只能用来修饰OC对象, 而且相比assign比较安全, 如果指向的对象消失了, 那么它会自动置为nil, 不会导致野指针。

ARC 是 LLVM + Runtime 互相协作的结果

开启ARC后, LLVM编译器会自动帮我们在相应位置生成 release、retain、autorelease

在作用域 (大括号) 结束的位置添加 release

弱引用这种, 是通过runtime处理的

编译之后的weak, 通过 objc_ownership(weak) 实现 weak 方法, objc_ownership 字面意思是:获得对象的所有权, 是对对象weak的初始化的一个操作。

通过 weak 编译解析, 可以看出 weak 是通过 runtime 初始化并维护的;

weak 和 strong 都是 OC ARC 的修饰词, 而 strong 是通过 runtime 维护的一个自动计数表结构。

weak 指针的地址值是所指对象指针的地址

weak 全局表 weak_table_t 中的存储 weak 定义的对象的表结构 weak_entry_t,

weak_entry_t 是存储在弱引用表中的一个内部结构体, 它负责维护和存储指向一个对象的 所有弱引用hash表

可以看到 DisguisedPtr<objc_object *> 相当于 objc_object ** ;

即 weak_referrer_t 就是 objc_object ** 的别名

初始化weak变量时, runtime会调用 objc_initWeak 函数, 初始化新的weak指针指向对象的地址;

objc_initWeak 函数内部会调用 objc_storeWeak() 函数, objc_storeWeak() 函数的作用是用来更新指针的指向, 创建弱引用表。

在最后会调用 clearDeallocating 函数。而 clearDeallocating 函数首先根据对象的地址获取weak指针地址的数组, 然后紧接着遍历这个数组, 将其中的数组开始置为nil, 把这个 entry从weak 表中删除, 最后一步清理对象的记录。

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

将弱引用存到一个弱引用表(哈希表)中, 对象销毁时, 就从表中取出当前对象的弱引用并清除

注: 关于 SideTable 、 weak_table_t 、 weak_entry_t 参考 《 isa指针 》