返回
Block 的本质(三)—— 基础类型的变量捕获
IOS
2023-11-28 13:10:20
我们一直在探索 Block 的底层结构。上一篇中,我们分析了 。这一次,我们进一步扩展,在 Block 中添加两个参数 a 和 b。按照惯例,我们使用命令
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m
编译并反汇编 main.m 文件,得到汇编代码如下:
_block_impl_0:
.align 3
.quad __block_descriptor_tmp0
.quad captured_a
.quad captured_b
.long 0
.long 2
__block_descriptor_tmp0:
.long 0 // flags
.long 1 // isa
.long _block_func_impl_0 // Implementation pointer
.long _descriptor // Block descriptor
与上一篇相比,汇编代码的变化之处在于,增加了 captured_a 和 captured_b 两个符号。这两个符号分别对应着 Block 中的两个参数 a 和 b。在 Block 的实现中,这两个参数被捕获到了 Block 内部,并存储在了 Block 的数据结构中。
现在,我们来分析一下 Block 数据结构的布局。Block 数据结构的第一个成员是 flags,它是一个 long 型变量,用于存储 Block 的一些标志位,比如 Block 是否可以被复制、是否可以被释放等。第二个成员是 isa,它是一个指向 Block 类对象的指针,用于标识 Block 的类型。第三个成员是 _block_func_impl_0,它是一个指向 Block 实现函数的指针,用于指定当 Block 被调用时应该执行哪个函数。第四个成员是 _descriptor,它是一个指向 Block 符的指针,用于 Block 的一些属性,比如 Block 的捕获变量列表、Block 的返回值类型等。
在 Block 的数据结构中,捕获变量被存储在 flags 之后的连续内存空间中。在本例中,参数 a 和 b 分别被存储在了 captured_a 和 captured_b 两个符号对应的内存空间中。
希望通过这三篇文章,你已经对 Block 的本质有了一个基本的了解。在下一篇文章中,我们将继续深入分析 Block,探讨 Block 的内存管理和释放机制。