swift开发知识收集

汇编窥探Swift底层(四):闭包

2020-02-27  本文已影响0人  冰风v落叶

窥探闭包的内存

闭包:一个函数和它所捕获的变量\常量环境组合起来,称为闭包

typealias Fn = (Int) -> Int

func getFn() -> Fn{
    func plus(_ i: Int) -> Int{
        return i
    }
    return plus
}

var fn = getFn()
print(fn(1))    输出1
print(fn(2))    输出2
print(fn(3))    输出3
print(fn(4))    输出4
TestSwift`getFn():
    0x100001320 <+0>:  pushq  %rbp
    0x100001321 <+1>:  movq   %rsp, %rbp
    0x100001324 <+4>:  leaq   0x15(%rip), %rax          ; plus #1 (Swift.Int) -> Swift.Int in TestEnumMemory.getFn() -> (Swift.Int) -> Swift.Int at main.swift:92
->  0x10000132b <+11>: xorl   %ecx, %ecx
    0x10000132d <+13>: movl   %ecx, %edx
    0x10000132f <+15>: popq   %rbp
    0x100001330 <+16>: retq   

typealias Fn = (Int) -> Int

func getFn() -> Fn{
    var num = 0          //增加了这一行
    func plus(_ i: Int) -> Int{
        num = num + i    //增加了这一行
        return num       //返回值变成了num+i
    }
    return plus          //返回的plus函数和捕获num产生的堆空间形成了闭包
}

var fn = getFn()
print(fn(1))    输出1
print(fn(2))    输出3
print(fn(3))    输出6
print(fn(4))    输出10
TestSwift`getFn():
    0x100001120 <+0>:  pushq  %rbp
    0x100001121 <+1>:  movq   %rsp, %rbp
    0x100001124 <+4>:  subq   $0x20, %rsp
    0x100001128 <+8>:  leaq   0x5009(%rip), %rdi
    0x10000112f <+15>: movl   $0x18, %esi
    0x100001134 <+20>: movl   $0x7, %edx
    0x100001139 <+25>: callq  0x10000543a               ; symbol stub for: swift_allocObject
    0x10000113e <+30>: movq   %rax, %rdx
    0x100001141 <+33>: addq   $0x10, %rdx
    0x100001145 <+37>: movq   %rdx, %rsi
    0x100001148 <+40>: movq   $0x0, 0x10(%rax)
->  0x100001150 <+48>: movq   %rax, %rdi
    0x100001153 <+51>: movq   %rax, -0x8(%rbp)
    0x100001157 <+55>: movq   %rdx, -0x10(%rbp)
    0x10000115b <+59>: callq  0x1000054b2               ; symbol stub for: swift_retain
    0x100001160 <+64>: movq   -0x8(%rbp), %rdi
    0x100001164 <+68>: movq   %rax, -0x18(%rbp)
    0x100001168 <+72>: callq  0x1000054ac               ; symbol stub for: swift_release
    0x10000116d <+77>: movq   -0x10(%rbp), %rax
    0x100001171 <+81>: leaq   0x1e8(%rip), %rax         ; partial apply forwarder for plus #1 (Swift.Int) -> Swift.Int in TestSwift.getFn() -> (Swift.Int) -> Swift.Int at <compiler-generated>
    0x100001178 <+88>: movq   -0x8(%rbp), %rdx
    0x10000117c <+92>: addq   $0x20, %rsp
    0x100001180 <+96>: popq   %rbp
    0x100001181 <+97>: retq   

(lldb) x/5xg  0x0000000100697b10
0x100697b10: 0x0000000100006138 0x0000000000000002
0x100697b20: 0x0000000000000000 0x0002000000000000
0x100697b30: 0x0000000000000000
调用fn(1)后,堆空间的数据变成了下面的样子
(lldb) x/5xg  0x0000000100697b10
0x100697b10: 0x0000000100006138 0x0000000200000002
0x100697b20: 0x0000000000000001 0x0002000000000000
0x100697b30: 0x0000000000000000
调用fn(2)后,堆空间的数据变成了下面的样子
(lldb) x/5xg  0x0000000100697b10
0x100697b10: 0x0000000100006138 0x0000000200000002
0x100697b20: 0x0000000000000003 0x0002000000000000
0x100697b30: 0x0000000000000000
调用fn(3)后,堆空间的数据变成了下面的样子
(lldb) x/5xg  0x0000000100697b10
0x100697b10: 0x0000000100006138 0x0000000200000002
0x100697b20: 0x0000000000000006 0x0002000000000000
0x100697b30: 0x0000000000000000
调用fn(4)后,堆空间的数据变成了下面的样子
(lldb) x/5xg  0x0000000100697b10
0x100697b10: 0x0000000100006138 0x0000000200000002
0x100697b20: 0x000000000000000a 0x0002000000000000
0x100697b30: 0x0000000000000000
class Closure{
    var num = 0
    func plus(_ i: Int) -> Int{
        num = num + i
        return num
    }
}
var closure = Closure()
print(closure.plus(1))  输出1
print(closure.plus(2))  输出3
print(closure.plus(3))  输出6
print(closure.plus(4))  输出10
15. 总结
上一篇 下一篇

猜你喜欢

热点阅读