一、闭包
1. 请问下面代码的输出?
问题- 输出
11 14
- num 是在
getFn 调用
,并且return plus
之前捕获的
2. 下面代码会对 person1 进行捕获吗?
题目- 从汇编来看不会捕获,fn1 后 8 个字节存放了 person1 的地址值
3. 下面函数打印什么?
image.png- 打印
1 2 3
- 应该是三次驳货
二、探索普通函数变量的内存放着什么?
1. 首先我们探索一下,一个正常的普通函数变量,它所占据的字节大小?
func sum(_ v1: Int, _ v2: Int) -> Int { v1 + v2 }
var fn = sum
print(MemoryLayout.stride(ofValue: fn))
// 输出: 16
- 输出 16,表示普通函数,Swift 给他分配了 16 个字节
- 按照我们的理解,正常情况下一个函数的地址仅需要 8 个字节,那么 16 个字节到底放着什么呢?
2. 我们在上题函数的 print行
打上断点,进入汇编模式
汇编图
-
%rcx
是 sum 函数的地址,赋值给了 fn 的前 8 个字节
-
0x0
赋值给了 fn 的后 8 个字节
- 另外我们可以计算 sum 的地址,然后打印 sum 的地址,两者一致,表示我们的猜想正确
三、探索闭包变量的内存放着什么?
1. 闭包变量代码如下
闭包变量- 进入汇编模式,查看
fn1
的16 字节
放着什么?
- 从汇编代码结合 xcode 提示,我们知道%rax 赋值给了 fn1 的前 8 个字节
- %rdx 赋值给了 fn1 的后 8 个字节
2. 接下来我们要弄懂 %rax 和 %rdx 分别存放什么?
-
%rax 和 %rdx 通常放着函数的返回值,所以我们要弄懂 callq 函数里面给这两个寄存器放了啥?
-
所以我们需要在 return plus 行打上断点
汇编以及分析 -
register read rax 查看获得
rax = 0x0000000100000e80
-
register read rdx 查看获得
rdx= 0x0000000100575170
3. 接下来我们要继续跟进,确认 %rdx 到底存放什么?
- 我们进入
callq 0x100000ea6
网友评论