美文网首页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