美文网首页swift开发知识收集
汇编窥探Swift底层(六):数组

汇编窥探Swift底层(六):数组

作者: 冰风v落叶 | 来源:发表于2020-03-01 12:25 被阅读0次

窥探数组的内存

    1. 我们知道Swift中的数组是结构体,也就是值类型,那么数组的内存究竟是什么样子呢,会不会像自定义的结构体一样,把数据存放到栈空间呢?


      Swift中的数组是结构体.png
    1. 我们定义一个数组,先来看看这个变量占用了多少个字节的空间,我们打印了一下,发现arr变量占用了8个字节,这8个字节明显存储不了40个字节的数据,我们来看看这8个字节究竟存储了什么?
var arr = [7,9,6,3,8]
print(MemoryLayout.stride(ofValue: arr)) 打印出来是8个字节
    1. 我们来看看这段代码的汇编,为了摒除干扰,把打印的代码注释掉,只留下了var arr = [7,9,6,3,8],汇编如下所示
TestSwift`main:
    0x100001380 <+0>:   pushq  %rbp
    0x100001381 <+1>:   movq   %rsp, %rbp
    0x100001384 <+4>:   subq   $0x10, %rsp
    0x100001388 <+8>:   movq   0x4ce1(%rip), %rax        ; (void *)0x00007fff8feeaa88: type metadata for Swift.Int
->  0x10000138f <+15>:  movl   $0x5, %ecx
    0x100001394 <+20>:  movl   %edi, -0x4(%rbp)
    0x100001397 <+23>:  movq   %rcx, %rdi
    0x10000139a <+26>:  movq   %rsi, -0x10(%rbp)
    0x10000139e <+30>:  movq   %rax, %rsi
    0x1000013a1 <+33>:  callq  0x10000548a               ; symbol stub for: Swift._allocateUninitializedArray<A>(Builtin.Word) -> (Swift.Array<A>, Builtin.RawPointer)
    0x1000013a6 <+38>:  movq   0x4cc3(%rip), %rsi        ; (void *)0x00007fff8feeaa88: type metadata for Swift.Int
    0x1000013ad <+45>:  movq   $0x7, (%rdx)
    0x1000013b4 <+52>:  movq   $0x9, 0x8(%rdx)
    0x1000013bc <+60>:  movq   $0x6, 0x10(%rdx)
    0x1000013c4 <+68>:  movq   $0x3, 0x18(%rdx)
    0x1000013cc <+76>:  movq   $0x8, 0x20(%rdx)
    0x1000013d4 <+84>:  movq   %rax, %rdi
    0x1000013d7 <+87>:  callq  0x100005436               ; symbol stub for: Swift.Array.init(arrayLiteral: A...) -> Swift.Array<A>
    0x1000013dc <+92>:  xorl   %r8d, %r8d
    0x1000013df <+95>:  movq   %rax, 0x5e02(%rip)        ; TestSwift.arr : Swift.Array<Swift.Int>
    0x1000013e6 <+102>: movl   %r8d, %eax
    0x1000013e9 <+105>: addq   $0x10, %rsp
    0x1000013ed <+109>: popq   %rbp
    0x1000013ee <+110>: retq   
    1. 重点看这一句movq %rax, 0x5e02(%rip) ; TestSwift.arr : Swift.Array<Swift.Int>,从注释可以看出来arr变量存储的数据就是rax寄存器的值,如下所示,打印出来是0x00000001034000f0,熟悉内存的朋友,很容易就可以看出来,这个地址是堆空间的地址
(lldb) register read rax
 rax = 0x00000001034000f0
    1. 我们利用LLDB命令x/10xg 0x00000001034000f0,来看看这个堆空间地址,到底存储了什么,如下所示,打印出来,发现我们的数据[7,9,6,3,8],就在这个堆空间第33个字节往后的位置
(lldb) x/10xg 0x00000001034000f0
0x1034000f0: 0x00007fff9cc33260 0x0000000000000002
0x103400100: 0x0000000000000005 0x000000000000000a
0x103400110: 0x0000000000000007 0x0000000000000009
0x103400120: 0x0000000000000006 0x0000000000000003
0x103400130: 0x0000000000000008 0x0000000000000000
    1. 我没有搞清楚前8个字节的作用,但是后面的字节,通过多次改变数组大小,查看堆空间后,我大致可以猜到了,第二组8个字节存放的应该是引用计数,第三组8个字节是数组的元素数量,第四组应该是数组的容量,再往后的字节,才是我们存储的数据,如下所示


      数组的内存
    1. 从上述分析,我们就可以知道,数组看起来是结构体+值类型,本质上还是引用类型,只不过我们可以按照结构体的用法来使用

相关文章

网友评论

    本文标题:汇编窥探Swift底层(六):数组

    本文链接:https://www.haomeiwen.com/subject/antfkhtx.html