返回
Block(下)- 底层源码分析
IOS
2023-11-12 13:42:12
前言
在前一篇文章中,我们学习了Block的三种表现形式,了解了引用计数和循环引用的相关知识。在这篇文章中,我们将进一步深入探讨Block的底层实现,探究其内部结构、copy机制和循环引用处理。通过对Block底层原理的剖析,帮助读者更好地理解Block的运行机制和内存管理细节,以便在实际开发中更加熟练地使用Block。
Block的底层结构
Block在底层是由C语言实现的,其本质上是一个函数指针,指向一个由编译器生成的函数。这个函数包含了Block的实现代码,以及对捕获变量的引用。Block的结构如下:
struct Block_layout {
void *isa; // 指向Block的类型信息
int flags; // Block的标志位,用于标记Block的属性
int reserved; // 保留字段
void (*invoke)(void *, ...); // 指向Block实现代码的函数指针
struct Block_descriptor *descriptor; // 指向Block符的指针
};
isa
:指向Block的类型信息,用于确定Block的类型。flags
:Block的标志位,用于标记Block的属性,如是否可复制、是否可捕获变量等。reserved
:保留字段,用于将来扩展使用。invoke
:指向Block实现代码的函数指针,当Block被调用时,会跳转到这个函数执行。descriptor
:指向Block符的指针,Block描述符包含了Block捕获变量的信息。
Block的Copy机制
Block是可复制的,这意味着可以创建Block的副本,副本与原Block具有相同的功能。Block的copy机制是通过创建一个新的Block结构体来实现的,新的Block结构体包含了与原Block相同的函数指针和Block描述符,但捕获变量的引用会被复制一份。
Block的copy过程如下:
- 分配内存空间来存储新的Block结构体。
- 将原Block的函数指针和Block描述符复制到新的Block结构体中。
- 将原Block捕获变量的引用复制到新的Block结构体中。
- 将新的Block结构体的地址返回给调用者。
Block的循环引用处理
Block可以捕获变量,这可能会导致循环引用。循环引用是指两个或多个对象相互引用,导致内存无法被释放。为了防止循环引用,Block在底层实现了循环引用检测和处理机制。
Block的循环引用检测机制如下:
- 当Block被创建时,会将Block描述符添加到一个全局的循环引用检测表中。
- 当Block被释放时,会从循环引用检测表中删除Block描述符。
- 当循环引用检测表中只剩下一个Block描述符时,说明该Block及其捕获变量已经成为循环引用,此时会触发循环引用处理机制。
Block的循环引用处理机制如下:
- 将Block描述符从循环引用检测表中删除。
- 释放Block捕获变量的内存空间。
- 释放Block结构体的内存空间。
结语
通过对Block底层源码的分析,我们深入了解了Block的内部结构、copy机制和循环引用处理。这些知识对于我们理解Block的运行机制和内存管理细节非常重要,有助于我们在实际开发中更加熟练地使用Block。