简述runtime 如何实现 k weak 变量的自动置 nil ?知道 SideTable 吗? ?
在 Objective-C 的 runtime 系统中,weak 变量能够自动置为 nil 的机制是依赖于一系列复杂的操作和数据结构来实现的。这个机制确保了当所引用的对象被释放时,weak 指针能够自动变为 nil,从而避免了野指针的问题。
首先,当在 runtime 中注册一个类时,系统会为这个类布局一个 weak 表(通常是一个 hash 表),其中 key 是所指对象的地址,value 是指向 weak 指针地址的数组。这个 weak 表用于存储和管理所有的 weak 引用。
接下来,我们来看一下 weak 变量自动置 nil 的具体实现步骤:
-
初始化 weak 指针:当创建一个 weak 引用时,runtime 会调用
objc_initWeak
函数来初始化这个 weak 指针,并将其加入到对应对象的 weak 表中。 -
更新 weak 指针:当 weak 指针需要更新其指向的对象时(例如,赋值操作),runtime 会调用
objc_storeWeak
函数。这个函数会更新 weak 指针的值,并在 weak 表中创建或更新对应的弱引用记录。 -
对象释放:当对象被释放时,会触发一系列的清理操作。在这个过程中,runtime 会调用
clearDeallocating
函数来处理 weak 引用。这个函数首先会根据对象的地址从 weak 表中获取所有 weak 指针地址的数组,然后遍历这个数组,将数组中的每个 weak 指针都置为 nil。接着,它还会将这个 entry(即对象的 weak 引用记录)从 weak 表中删除。最后,完成对象的内存清理工作。
在这个过程中,为了保证线程安全,防止多线程环境下的竞争冲突,runtime 还会使用锁机制来确保操作的原子性。
关于 SideTable,它是 runtime 内存空间中的一个重要组成部分。SideTable 可以看作是一个 hash 数组,用于存储和管理与对象相关的各种信息。其中,每个 SideTable 对应多个对象,因为 SideTable 的数量是有限的(通常是 64 个),所以会有多个对象共享同一个 SideTable。在 SideTable 中,主要存放了 OC 对象的引用计数和弱引用相关信息。特别是 weak_table,它存储了弱引用对象的指针地址,这对于实现 weak 变量的自动置 nil 机制至关重要。
总的来说,runtime 通过 weak 表和 SideTable 等数据结构,以及一系列复杂的操作,实现了 weak 变量的自动置 nil 功能,从而提高了程序的健壮性和安全性。