函数执行顺序

  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

    C++对象构造和析构

    //遗留的问题:C++中构造函数和析构函数的执行顺序到底是怎么样的呢?
    class Object
    {
    private:
        int val;
    public:
        Object(int x)
        {
            val = x;
            cout << "create :" << val << endl;
        }    
    };
    Object o1(1);
    
    int main()
    {
        Object o2(2);
    }
    
    Object o3(3);
    

    代码在Linux64平台编译运行,objdump -d 生成反汇编代码

    汇编代码如下:

    反汇编代码
    Object:     文件格式 elf64-x86-64
    
    Disassembly of section .init:
    
    0000000000001000 <_init>:
        1000:       f3 0f 1e fa             endbr64 
        1004:       48 83 ec 08             sub    $0x8,%rsp
        1008:       48 8b 05 d9 2f 00 00    mov    0x2fd9(%rip),%rax        # 3fe8 <__gmon_start__>
        100f:       48 85 c0                test   %rax,%rax
        1012:       74 02                   je     1016 <_init+0x16>
        1014:       ff d0                   callq  *%rax
        1016:       48 83 c4 08             add    $0x8,%rsp
        101a:       c3                      retq   
    
    Disassembly of section .plt:
    
    0000000000001020 <.plt>:
        1020:       ff 35 62 2f 00 00       pushq  0x2f62(%rip)        # 3f88 <_GLOBAL_OFFSET_TABLE_+0x8>
        1026:       f2 ff 25 63 2f 00 00    bnd jmpq *0x2f63(%rip)        # 3f90 <_GLOBAL_OFFSET_TABLE_+0x10>
        102d:       0f 1f 00                nopl   (%rax)
        1030:       f3 0f 1e fa             endbr64 
        1034:       68 00 00 00 00          pushq  $0x0
        1039:       f2 e9 e1 ff ff ff       bnd jmpq 1020 <.plt>
        103f:       90                      nop
        1040:       f3 0f 1e fa             endbr64 
        1044:       68 01 00 00 00          pushq  $0x1
        1049:       f2 e9 d1 ff ff ff       bnd jmpq 1020 <.plt>
        104f:       90                      nop
        1050:       f3 0f 1e fa             endbr64 
        1054:       68 02 00 00 00          pushq  $0x2
        1059:       f2 e9 c1 ff ff ff       bnd jmpq 1020 <.plt>
        105f:       90                      nop
        1060:       f3 0f 1e fa             endbr64 
        1064:       68 03 00 00 00          pushq  $0x3
        1069:       f2 e9 b1 ff ff ff       bnd jmpq 1020 <.plt>
        106f:       90                      nop
        1070:       f3 0f 1e fa             endbr64 
        1074:       68 04 00 00 00          pushq  $0x4
        1079:       f2 e9 a1 ff ff ff       bnd jmpq 1020 <.plt>
        107f:       90                      nop
        1080:       f3 0f 1e fa             endbr64 
        1084:       68 05 00 00 00          pushq  $0x5
        1089:       f2 e9 91 ff ff ff       bnd jmpq 1020 <.plt>
        108f:       90                      nop
    
    Disassembly of section .plt.got:
    
    0000000000001090 <__cxa_finalize@plt>:
        1090:       f3 0f 1e fa             endbr64 
        1094:       f2 ff 25 2d 2f 00 00    bnd jmpq *0x2f2d(%rip)        # 3fc8 <__cxa_finalize@GLIBC_2.2.5>
        109b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
    
    Disassembly of section .plt.sec:
    
    00000000000010a0 <__cxa_atexit@plt>:
        10a0:       f3 0f 1e fa             endbr64 
        10a4:       f2 ff 25 ed 2e 00 00    bnd jmpq *0x2eed(%rip)        # 3f98 <__cxa_atexit@GLIBC_2.2.5>
        10ab:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
    
    00000000000010b0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>:
        10b0:       f3 0f 1e fa             endbr64 
        10b4:       f2 ff 25 e5 2e 00 00    bnd jmpq *0x2ee5(%rip)        # 3fa0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@GLIBCXX_3.4>
        10bb:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
    
    00000000000010c0 <_ZNSolsEPFRSoS_E@plt>:
        10c0:       f3 0f 1e fa             endbr64 
        10c4:       f2 ff 25 dd 2e 00 00    bnd jmpq *0x2edd(%rip)        # 3fa8 <_ZNSolsEPFRSoS_E@GLIBCXX_3.4>
        10cb:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
    
    00000000000010d0 <__stack_chk_fail@plt>:
        10d0:       f3 0f 1e fa             endbr64 
        10d4:       f2 ff 25 d5 2e 00 00    bnd jmpq *0x2ed5(%rip)        # 3fb0 <__stack_chk_fail@GLIBC_2.4>
        10db:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
    
    00000000000010e0 <_ZNSt8ios_base4InitC1Ev@plt>:
        10e0:       f3 0f 1e fa             endbr64 
        10e4:       f2 ff 25 cd 2e 00 00    bnd jmpq *0x2ecd(%rip)        # 3fb8 <_ZNSt8ios_base4InitC1Ev@GLIBCXX_3.4>
        10eb:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
    
    00000000000010f0 <_ZNSolsEi@plt>:
        10f0:       f3 0f 1e fa             endbr64 
        10f4:       f2 ff 25 c5 2e 00 00    bnd jmpq *0x2ec5(%rip)        # 3fc0 <_ZNSolsEi@GLIBCXX_3.4>
        10fb:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
    
    Disassembly of section .text:
    
    0000000000001100 <_start>:
        1100:       f3 0f 1e fa             endbr64 
        1104:       31 ed                   xor    %ebp,%ebp
        1106:       49 89 d1                mov    %rdx,%r9
        1109:       5e                      pop    %rsi
        110a:       48 89 e2                mov    %rsp,%rdx
        110d:       48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
        1111:       50                      push   %rax
        1112:       54                      push   %rsp
        1113:       4c 8d 05 f6 02 00 00    lea    0x2f6(%rip),%r8        # 1410 <__libc_csu_fini>
        111a:       48 8d 0d 7f 02 00 00    lea    0x27f(%rip),%rcx        # 13a0 <__libc_csu_init>
        1121:       48 8d 3d c1 00 00 00    lea    0xc1(%rip),%rdi        # 11e9 <main>
        1128:       ff 15 b2 2e 00 00       callq  *0x2eb2(%rip)        # 3fe0 <__libc_start_main@GLIBC_2.2.5>
        112e:       f4                      hlt    
        112f:       90                      nop
    
    0000000000001130 <deregister_tm_clones>:
        1130:       48 8d 3d e1 2e 00 00    lea    0x2ee1(%rip),%rdi        # 4018 <__TMC_END__>
        1137:       48 8d 05 da 2e 00 00    lea    0x2eda(%rip),%rax        # 4018 <__TMC_END__>
        113e:       48 39 f8                cmp    %rdi,%rax
        1141:       74 15                   je     1158 <deregister_tm_clones+0x28>
        1143:       48 8b 05 8e 2e 00 00    mov    0x2e8e(%rip),%rax        # 3fd8 <_ITM_deregisterTMCloneTable>
        114a:       48 85 c0                test   %rax,%rax
        114d:       74 09                   je     1158 <deregister_tm_clones+0x28>
        114f:       ff e0                   jmpq   *%rax
        1151:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
        1158:       c3                      retq   
        1159:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
    
    0000000000001160 <register_tm_clones>:
        1160:       48 8d 3d b1 2e 00 00    lea    0x2eb1(%rip),%rdi        # 4018 <__TMC_END__>
        1167:       48 8d 35 aa 2e 00 00    lea    0x2eaa(%rip),%rsi        # 4018 <__TMC_END__>
        116e:       48 29 fe                sub    %rdi,%rsi
        1171:       48 89 f0                mov    %rsi,%rax
        1174:       48 c1 ee 3f             shr    $0x3f,%rsi
        1178:       48 c1 f8 03             sar    $0x3,%rax
        117c:       48 01 c6                add    %rax,%rsi
        117f:       48 d1 fe                sar    %rsi
        1182:       74 14                   je     1198 <register_tm_clones+0x38>
        1184:       48 8b 05 65 2e 00 00    mov    0x2e65(%rip),%rax        # 3ff0 <_ITM_registerTMCloneTable>
        118b:       48 85 c0                test   %rax,%rax
        118e:       74 08                   je     1198 <register_tm_clones+0x38>
        1190:       ff e0                   jmpq   *%rax
        1192:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
        1198:       c3                      retq   
        1199:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
    
    00000000000011a0 <__do_global_dtors_aux>:
        11a0:       f3 0f 1e fa             endbr64 
        11a4:       80 3d a5 2f 00 00 00    cmpb   $0x0,0x2fa5(%rip)        # 4150 <completed.8060>
        11ab:       75 2b                   jne    11d8 <__do_global_dtors_aux+0x38>
        11ad:       55                      push   %rbp
        11ae:       48 83 3d 12 2e 00 00    cmpq   $0x0,0x2e12(%rip)        # 3fc8 <__cxa_finalize@GLIBC_2.2.5>
        11b5:       00 
        11b6:       48 89 e5                mov    %rsp,%rbp
        11b9:       74 0c                   je     11c7 <__do_global_dtors_aux+0x27>
        11bb:       48 8b 3d 46 2e 00 00    mov    0x2e46(%rip),%rdi        # 4008 <__dso_handle>
        11c2:       e8 c9 fe ff ff          callq  1090 <__cxa_finalize@plt>
        11c7:       e8 64 ff ff ff          callq  1130 <deregister_tm_clones>
        11cc:       c6 05 7d 2f 00 00 01    movb   $0x1,0x2f7d(%rip)        # 4150 <completed.8060>
        11d3:       5d                      pop    %rbp
        11d4:       c3                      retq   
        11d5:       0f 1f 00                nopl   (%rax)
        11d8:       c3                      retq   
        11d9:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
    
    00000000000011e0 <frame_dummy>:
        11e0:       f3 0f 1e fa             endbr64 
        11e4:       e9 77 ff ff ff          jmpq   1160 <register_tm_clones>
    
    00000000000011e9 <main>:
        11e9:       f3 0f 1e fa             endbr64 
        11ed:       55                      push   %rbp
        11ee:       48 89 e5                mov    %rsp,%rbp
        11f1:       48 83 ec 10             sub    $0x10,%rsp
        11f5:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
        11fc:       00 00 
        11fe:       48 89 45 f8             mov    %rax,-0x8(%rbp)
        1202:       31 c0                   xor    %eax,%eax
        1204:       48 8d 45 f4             lea    -0xc(%rbp),%rax
        1208:       be 02 00 00 00          mov    $0x2,%esi
        120d:       48 89 c7                mov    %rax,%rdi
        1210:       e8 e7 00 00 00          callq  12fc <_ZN6ObjectC1Ei>
        1215:       48 8d 45 f4             lea    -0xc(%rbp),%rax
        1219:       48 89 c7                mov    %rax,%rdi
        121c:       e8 35 01 00 00          callq  1356 <_ZN6ObjectD1Ev>
        1221:       b8 00 00 00 00          mov    $0x0,%eax
        1226:       48 8b 55 f8             mov    -0x8(%rbp),%rdx
        122a:       64 48 33 14 25 28 00    xor    %fs:0x28,%rdx
        1231:       00 00 
        1233:       74 05                   je     123a <main+0x51>
        1235:       e8 96 fe ff ff          callq  10d0 <__stack_chk_fail@plt>
        123a:       c9                      leaveq 
        123b:       c3                      retq   
    
    000000000000123c <_Z41__static_initialization_and_destruction_0ii>:
        123c:       f3 0f 1e fa             endbr64 
        1240:       55                      push   %rbp
        1241:       48 89 e5                mov    %rsp,%rbp
        1244:       48 83 ec 10             sub    $0x10,%rsp
        1248:       89 7d fc                mov    %edi,-0x4(%rbp)
        124b:       89 75 f8                mov    %esi,-0x8(%rbp)
        124e:       83 7d fc 01             cmpl   $0x1,-0x4(%rbp)
        1252:       0f 85 88 00 00 00       jne    12e0 <_Z41__static_initialization_and_destruction_0ii+0xa4>
        1258:       81 7d f8 ff ff 00 00    cmpl   $0xffff,-0x8(%rbp)
        125f:       75 7f                   jne    12e0 <_Z41__static_initialization_and_destruction_0ii+0xa4>
        1261:       48 8d 3d f4 2e 00 00    lea    0x2ef4(%rip),%rdi        # 415c <_ZStL8__ioinit>
        1268:       e8 73 fe ff ff          callq  10e0 <_ZNSt8ios_base4InitC1Ev@plt>
        126d:       48 8d 15 94 2d 00 00    lea    0x2d94(%rip),%rdx        # 4008 <__dso_handle>
        1274:       48 8d 35 e1 2e 00 00    lea    0x2ee1(%rip),%rsi        # 415c <_ZStL8__ioinit>
        127b:       48 8b 05 76 2d 00 00    mov    0x2d76(%rip),%rax        # 3ff8 <_ZNSt8ios_base4InitD1Ev@GLIBCXX_3.4>
        1282:       48 89 c7                mov    %rax,%rdi
        1285:       e8 16 fe ff ff          callq  10a0 <__cxa_atexit@plt>
        128a:       be 01 00 00 00          mov    $0x1,%esi
        128f:       48 8d 3d be 2e 00 00    lea    0x2ebe(%rip),%rdi        # 4154 <o1>
        1296:       e8 61 00 00 00          callq  12fc <_ZN6ObjectC1Ei>
        129b:       48 8d 15 66 2d 00 00    lea    0x2d66(%rip),%rdx        # 4008 <__dso_handle>
        12a2:       48 8d 35 ab 2e 00 00    lea    0x2eab(%rip),%rsi        # 4154 <o1>
        12a9:       48 8d 3d a6 00 00 00    lea    0xa6(%rip),%rdi        # 1356 <_ZN6ObjectD1Ev>
        12b0:       e8 eb fd ff ff          callq  10a0 <__cxa_atexit@plt>
        12b5:       be 03 00 00 00          mov    $0x3,%esi
        12ba:       48 8d 3d 97 2e 00 00    lea    0x2e97(%rip),%rdi        # 4158 <o3>
        12c1:       e8 36 00 00 00          callq  12fc <_ZN6ObjectC1Ei>
        12c6:       48 8d 15 3b 2d 00 00    lea    0x2d3b(%rip),%rdx        # 4008 <__dso_handle>
        12cd:       48 8d 35 84 2e 00 00    lea    0x2e84(%rip),%rsi        # 4158 <o3>
        12d4:       48 8d 3d 7b 00 00 00    lea    0x7b(%rip),%rdi        # 1356 <_ZN6ObjectD1Ev>
        12db:       e8 c0 fd ff ff          callq  10a0 <__cxa_atexit@plt>
        12e0:       90                      nop
        12e1:       c9                      leaveq 
        12e2:       c3                      retq   
    
    00000000000012e3 <_GLOBAL__sub_I_o1>:
        12e3:       f3 0f 1e fa             endbr64 
        12e7:       55                      push   %rbp
        12e8:       48 89 e5                mov    %rsp,%rbp
        12eb:       be ff ff 00 00          mov    $0xffff,%esi
        12f0:       bf 01 00 00 00          mov    $0x1,%edi
        12f5:       e8 42 ff ff ff          callq  123c <_Z41__static_initialization_and_destruction_0ii>
        12fa:       5d                      pop    %rbp
        12fb:       c3                      retq   
    
    00000000000012fc <_ZN6ObjectC1Ei>:
        12fc:       f3 0f 1e fa             endbr64 
        1300:       55                      push   %rbp
        1301:       48 89 e5                mov    %rsp,%rbp
        1304:       48 83 ec 10             sub    $0x10,%rsp
        1308:       48 89 7d f8             mov    %rdi,-0x8(%rbp)
        130c:       89 75 f4                mov    %esi,-0xc(%rbp)
        130f:       48 8b 45 f8             mov    -0x8(%rbp),%rax
        1313:       8b 55 f4                mov    -0xc(%rbp),%edx
        1316:       89 10                   mov    %edx,(%rax)
        1318:       48 8d 35 e6 0c 00 00    lea    0xce6(%rip),%rsi        # 2005 <_ZStL19piecewise_construct+0x1>
        131f:       48 8d 3d 1a 2d 00 00    lea    0x2d1a(%rip),%rdi        # 4040 <_ZSt4cout@@GLIBCXX_3.4>
        1326:       e8 85 fd ff ff          callq  10b0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
        132b:       48 89 c2                mov    %rax,%rdx
        132e:       48 8b 45 f8             mov    -0x8(%rbp),%rax
        1332:       8b 00                   mov    (%rax),%eax
        1334:       89 c6                   mov    %eax,%esi
        1336:       48 89 d7                mov    %rdx,%rdi
        1339:       e8 b2 fd ff ff          callq  10f0 <_ZNSolsEi@plt>
        133e:       48 89 c2                mov    %rax,%rdx
        1341:       48 8b 05 88 2c 00 00    mov    0x2c88(%rip),%rax        # 3fd0 <_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GLIBCXX_3.4>
        1348:       48 89 c6                mov    %rax,%rsi
        134b:       48 89 d7                mov    %rdx,%rdi
        134e:       e8 6d fd ff ff          callq  10c0 <_ZNSolsEPFRSoS_E@plt>
        1353:       90                      nop
        1354:       c9                      leaveq 
        1355:       c3                      retq   
    
    0000000000001356 <_ZN6ObjectD1Ev>:
        1356:       f3 0f 1e fa             endbr64 
        135a:       55                      push   %rbp
        135b:       48 89 e5                mov    %rsp,%rbp
        135e:       48 83 ec 10             sub    $0x10,%rsp
        1362:       48 89 7d f8             mov    %rdi,-0x8(%rbp)
        1366:       48 8d 35 a1 0c 00 00    lea    0xca1(%rip),%rsi        # 200e <_ZStL19piecewise_construct+0xa>
        136d:       48 8d 3d cc 2c 00 00    lea    0x2ccc(%rip),%rdi        # 4040 <_ZSt4cout@@GLIBCXX_3.4>
        1374:       e8 37 fd ff ff          callq  10b0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
        1379:       48 89 c2                mov    %rax,%rdx
        137c:       48 8b 05 4d 2c 00 00    mov    0x2c4d(%rip),%rax        # 3fd0 <_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GLIBCXX_3.4>
        1383:       48 89 c6                mov    %rax,%rsi
        1386:       48 89 d7                mov    %rdx,%rdi
        1389:       e8 32 fd ff ff          callq  10c0 <_ZNSolsEPFRSoS_E@plt>
        138e:       90                      nop
        138f:       c9                      leaveq 
        1390:       c3                      retq   
        1391:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
        1398:       00 00 00 
        139b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
    
    00000000000013a0 <__libc_csu_init>:
        13a0:       f3 0f 1e fa             endbr64 
        13a4:       41 57                   push   %r15
        13a6:       4c 8d 3d bb 29 00 00    lea    0x29bb(%rip),%r15        # 3d68 <__frame_dummy_init_array_entry>
        13ad:       41 56                   push   %r14
        13af:       49 89 d6                mov    %rdx,%r14
        13b2:       41 55                   push   %r13
        13b4:       49 89 f5                mov    %rsi,%r13
        13b7:       41 54                   push   %r12
        13b9:       41 89 fc                mov    %edi,%r12d
        13bc:       55                      push   %rbp
        13bd:       48 8d 2d b4 29 00 00    lea    0x29b4(%rip),%rbp        # 3d78 <__do_global_dtors_aux_fini_array_entry>
        13c4:       53                      push   %rbx
        13c5:       4c 29 fd                sub    %r15,%rbp
        13c8:       48 83 ec 08             sub    $0x8,%rsp
        13cc:       e8 2f fc ff ff          callq  1000 <_init>
        13d1:       48 c1 fd 03             sar    $0x3,%rbp
        13d5:       74 1f                   je     13f6 <__libc_csu_init+0x56>
        13d7:       31 db                   xor    %ebx,%ebx
        13d9:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
        13e0:       4c 89 f2                mov    %r14,%rdx
        13e3:       4c 89 ee                mov    %r13,%rsi
        13e6:       44 89 e7                mov    %r12d,%edi
        13e9:       41 ff 14 df             callq  *(%r15,%rbx,8)
        13ed:       48 83 c3 01             add    $0x1,%rbx
        13f1:       48 39 dd                cmp    %rbx,%rbp
        13f4:       75 ea                   jne    13e0 <__libc_csu_init+0x40>
        13f6:       48 83 c4 08             add    $0x8,%rsp
        13fa:       5b                      pop    %rbx
        13fb:       5d                      pop    %rbp
        13fc:       41 5c                   pop    %r12
        13fe:       41 5d                   pop    %r13
        1400:       41 5e                   pop    %r14
        1402:       41 5f                   pop    %r15
        1404:       c3                      retq   
        1405:       66 66 2e 0f 1f 84 00    data16 nopw %cs:0x0(%rax,%rax,1)
        140c:       00 00 00 00 
    
    0000000000001410 <__libc_csu_fini>:
        1410:       f3 0f 1e fa             endbr64 
        1414:       c3                      retq   
    
    Disassembly of section .fini:
    
    0000000000001418 <_fini>:
        1418:       f3 0f 1e fa             endbr64 
        141c:       48 83 ec 08             sub    $0x8,%rsp
        1420:       48 83 c4 08             add    $0x8,%rsp
        1424:       c3                      retq  
    

    局部对象的构造和析构

    首先我们找到main函数的反汇编代码:

    00000000000011e9 <main>:
        11e9:       f3 0f 1e fa             endbr64 
        11ed:       55                      push   %rbp
        11ee:       48 89 e5                mov    %rsp,%rbp
        11f1:       48 83 ec 10             sub    $0x10,%rsp
        11f5:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
        11fc:       00 00 
        11fe:       48 89 45 f8             mov    %rax,-0x8(%rbp)
        1202:       31 c0                   xor    %eax,%eax
        1204:       48 8d 45 f4             lea    -0xc(%rbp),%rax
        1208:       be 02 00 00 00          mov    $0x2,%esi
        120d:       48 89 c7                mov    %rax,%rdi
        1210:       e8 e7 00 00 00          callq  12fc <_ZN6ObjectC1Ei>
        1215:       48 8d 45 f4             lea    -0xc(%rbp),%rax
        1219:       48 89 c7                mov    %rax,%rdi
        121c:       e8 35 01 00 00          callq  1356 <_ZN6ObjectD1Ev>
        1221:       b8 00 00 00 00          mov    $0x0,%eax
        1226:       48 8b 55 f8             mov    -0x8(%rbp),%rdx
        122a:       64 48 33 14 25 28 00    xor    %fs:0x28,%rdx
        1231:       00 00 
        1233:       74 05                   je     123a <main+0x51>
        1235:       e8 96 fe ff ff          callq  10d0 <__stack_chk_fail@plt>
        123a:       c9                      leaveq 
        123b:       c3                      retq   
    
    从main函数的反汇编代码中,我们可以看出,在main函数只构造了o2这一个对象,o2的构造函数被命名为 _ZN6ObjectC1Ei,析构函数被命名为 _ZN6ObjectD1Ev。

    第10行,将对象的地址传递给rax寄存器。

    第11行,将括号中的参数传递给寄存器esi。

    第12行,将rax寄存器的地址传递给隐藏参数&obj(this指针)。

    在第16行,调用析构函数,释放函数占用的资源。

    构造函数:

    00000000000012fc <_ZN6ObjectC1Ei>:
        12fc:       f3 0f 1e fa             endbr64 
        1300:       55                      push   %rbp
        1301:       48 89 e5                mov    %rsp,%rbp
        1304:       48 83 ec 10             sub    $0x10,%rsp
        1308:       48 89 7d f8             mov    %rdi,-0x8(%rbp)
        130c:       89 75 f4                mov    %esi,-0xc(%rbp)
        130f:       48 8b 45 f8             mov    -0x8(%rbp),%rax
        1313:       8b 55 f4                mov    -0xc(%rbp),%edx
        1316:       89 10                   mov    %edx,(%rax)
        1318:       48 8d 35 e6 0c 00 00    lea    0xce6(%rip),%rsi        # 2005 <_ZStL19piecewise_construct+0x1>
        131f:       48 8d 3d 1a 2d 00 00    lea    0x2d1a(%rip),%rdi        # 4040 <_ZSt4cout@@GLIBCXX_3.4>
        1326:       e8 85 fd ff ff          callq  10b0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
        132b:       48 89 c2                mov    %rax,%rdx
        132e:       48 8b 45 f8             mov    -0x8(%rbp),%rax
        1332:       8b 00                   mov    (%rax),%eax
        1334:       89 c6                   mov    %eax,%esi
        1336:       48 89 d7                mov    %rdx,%rdi
        1339:       e8 b2 fd ff ff          callq  10f0 <_ZNSolsEi@plt>
        133e:       48 89 c2                mov    %rax,%rdx
        1341:       48 8b 05 88 2c 00 00    mov    0x2c88(%rip),%rax        # 3fd0 <_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GLIBCXX_3.4>
        1348:       48 89 c6                mov    %rax,%rsi
        134b:       48 89 d7                mov    %rdx,%rdi
        134e:       e8 6d fd ff ff          callq  10c0 <_ZNSolsEPFRSoS_E@plt>
        1353:       90                      nop
        1354:       c9                      leaveq 
        1355:       c3                      retq   
    

    析构函数:

    0000000000001356 <_ZN6ObjectD1Ev>:
        1356:       f3 0f 1e fa             endbr64 
        135a:       55                      push   %rbp
        135b:       48 89 e5                mov    %rsp,%rbp
        135e:       48 83 ec 10             sub    $0x10,%rsp
        1362:       48 89 7d f8             mov    %rdi,-0x8(%rbp)
        1366:       48 8d 35 a1 0c 00 00    lea    0xca1(%rip),%rsi        # 200e <_ZStL19piecewise_construct+0xa>
        136d:       48 8d 3d cc 2c 00 00    lea    0x2ccc(%rip),%rdi        # 4040 <_ZSt4cout@@GLIBCXX_3.4>
        1374:       e8 37 fd ff ff          callq  10b0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
        1379:       48 89 c2                mov    %rax,%rdx
        137c:       48 8b 05 4d 2c 00 00    mov    0x2c4d(%rip),%rax        # 3fd0 <_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GLIBCXX_3.4>
        1383:       48 89 c6                mov    %rax,%rsi
        1386:       48 89 d7                mov    %rdx,%rdi
        1389:       e8 32 fd ff ff          callq  10c0 <_ZNSolsEPFRSoS_E@plt>
        138e:       90                      nop
        138f:       c9                      leaveq 
        1390:       c3                      retq   
        1391:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
        1398:       00 00 00 
        139b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
    

    全局对象的构造和析构

    从上述代码可以看出,局部对象o2的构造和析构在main函数中。

    那么全局对象o1和o3的构造和析构在哪呢?

    我们发现存在名字为<_Z41__static_initialization_and_destruction_0ii>的汇编代码:

    000000000000123c <_Z41__static_initialization_and_destruction_0ii>:
        123c:       f3 0f 1e fa             endbr64 
        1240:       55                      push   %rbp
        1241:       48 89 e5                mov    %rsp,%rbp
        1244:       48 83 ec 10             sub    $0x10,%rsp
        1248:       89 7d fc                mov    %edi,-0x4(%rbp)
        124b:       89 75 f8                mov    %esi,-0x8(%rbp)
        124e:       83 7d fc 01             cmpl   $0x1,-0x4(%rbp)
        1252:       0f 85 88 00 00 00       jne    12e0 <_Z41__static_initialization_and_destruction_0ii+0xa4>
        1258:       81 7d f8 ff ff 00 00    cmpl   $0xffff,-0x8(%rbp)
        125f:       75 7f                   jne    12e0 <_Z41__static_initialization_and_destruction_0ii+0xa4>
        1261:       48 8d 3d f4 2e 00 00    lea    0x2ef4(%rip),%rdi        # 415c <_ZStL8__ioinit>
        1268:       e8 73 fe ff ff          callq  10e0 <_ZNSt8ios_base4InitC1Ev@plt>
        126d:       48 8d 15 94 2d 00 00    lea    0x2d94(%rip),%rdx        # 4008 <__dso_handle>
        1274:       48 8d 35 e1 2e 00 00    lea    0x2ee1(%rip),%rsi        # 415c <_ZStL8__ioinit>
        127b:       48 8b 05 76 2d 00 00    mov    0x2d76(%rip),%rax        # 3ff8 <_ZNSt8ios_base4InitD1Ev@GLIBCXX_3.4>
        1282:       48 89 c7                mov    %rax,%rdi
        1285:       e8 16 fe ff ff          callq  10a0<__cxa_atexit@plt>
        128a:       be 01 00 00 00          mov    $0x1,%esi
        128f:       48 8d 3d be 2e 00 00    lea    0x2ebe(%rip),%rdi        # 4154 <o1>
        1296:       e8 61 00 00 00          callq  12fc <_ZN6ObjectC1Ei>
        129b:       48 8d 15 66 2d 00 00    lea    0x2d66(%rip),%rdx        # 4008 <__dso_handle>
        12a2:       48 8d 35 ab 2e 00 00    lea    0x2eab(%rip),%rsi        # 4154 <o1>
        12a9:       48 8d 3d a6 00 00 00    lea    0xa6(%rip),%rdi        # 1356 <_ZN6ObjectD1Ev>
        12b0:       e8 eb fd ff ff          callq  10a0<__cxa_atexit@plt>
        12b5:       be 03 00 00 00          mov    $0x3,%esi
        12ba:       48 8d 3d 97 2e 00 00    lea    0x2e97(%rip),%rdi        # 4158 <o3>
        12c1:       e8 36 00 00 00          callq  12fc <_ZN6ObjectC1Ei>
        12c6:       48 8d 15 3b 2d 00 00    lea    0x2d3b(%rip),%rdx        # 4008 <__dso_handle>
        12cd:       48 8d 35 84 2e 00 00    lea    0x2e84(%rip),%rsi        # 4158 <o3>
        12d4:       48 8d 3d 7b 00 00 00    lea    0x7b(%rip),%rdi        # 1356 <_ZN6ObjectD1Ev>
        12db:       e8 c0 fd ff ff          callq  10a0<__cxa_atexit@plt>
        12e0:       90                      nop
        12e1:       c9                      leaveq 
        12e2:       c3                      retq   
    
    

    静态对象(全局对象)初始化和析构。

    第21行调用构造函数,

    第25行调用回调函数,

    第28行调用构造函数。

    在这个函数中调用了静态对象(全局对象)的构造函数,并且将其析构函数通过_cxa_atexit函数注册,使其能在exit时调用。

    
     00000000000012e3 <_GLOBAL__sub_I_o1>:
        12e3:       f3 0f 1e fa             endbr64 
        12e7:       55                      push   %rbp
        12e8:       48 89 e5                mov    %rsp,%rbp
        12eb:       be ff ff 00 00          mov    $0xffff,%esi
        12f0:       bf 01 00 00 00          mov    $0x1,%edi
        12f5:       e8 42 ff ff ff          callq  123c <_Z41__static_initialization_and_destruction_0ii>
        12fa:       5d                      pop    %rbp
        12fb:       c3                      retq   
    

    _GLOBAL__sub_I_o1函数负责本编译单元所有全局\静态对象的构造和析构,那么这个函数在哪里被调用的呢?我们下面将查看程序是在哪开始执行的。

    实际上在Linux环境下,glibc程序执行的入口地址是_start,这个入口是由ld链接器默认的链接脚本所指定的,当然也可以通过相关参数设定自己的入口。

    程序的入口

    程序入口:_start

    0000000000001100 <_start>:
        1100:       f3 0f 1e fa             endbr64 
        1104:       31 ed                   xor    %ebp,%ebp
        1106:       49 89 d1                mov    %rdx,%r9
        1109:       5e                      pop    %rsi
        110a:       48 89 e2                mov    %rsp,%rdx
        110d:       48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
        1111:       50                      push   %rax
        1112:       54                      push   %rsp
        1113:       4c 8d 05 f6 02 00 00    lea    0x2f6(%rip),%r8        # 1410 <__libc_csu_fini>
        111a:       48 8d 0d 7f 02 00 00    lea    0x27f(%rip),%rcx        # 13a0 <__libc_csu_init>
        1121:       48 8d 3d c1 00 00 00    lea    0xc1(%rip),%rdi        # 11e9 <main>
        1128:       ff 15 b2 2e 00 00       callq  *0x2eb2(%rip)        # 3fe0 <__libc_start_main@GLIBC_2.2.5>
        112e:       f4                      hlt    
        112f:       90                      nop
    

    汇编中的注释非常清晰。

    第12行才是main函数的地址。

    __ libc_csu_init函数的地址是全局对象构造的地址。

    __ libc_csu_fini是全局对象析构的地址。

    从_ start的汇编代码可以看出,实际上_ start函数里面调用了_ libc_start_main函数,并把_libc_csu_init函数和__libc_csu_fini函数以及main函数的地址作为参数传递进去。

    由于__libc_start_main函数是在glibc动态链接库里的函数,所以可执行文件的反汇编代码中并没有这一部分的代码,不过我们只需要大概了解其中先后调用关系如下:

    --->_start

    ​ --->_lib_start_main

    ​ --->__ libc_csu_init

    ​ --->main

    ​ --->__libc_csu_fini

    _libc_csu_init函数

    00000000000013a0 <__libc_csu_init>:
        13a0:       f3 0f 1e fa             endbr64 
        13a4:       41 57                   push   %r15
        13a6:       4c 8d 3d bb 29 00 00    lea    0x29bb(%rip),%r15        # 3d68 <__frame_dummy_init_array_entry>
        13ad:       41 56                   push   %r14
        13af:       49 89 d6                mov    %rdx,%r14
        13b2:       41 55                   push   %r13
        13b4:       49 89 f5                mov    %rsi,%r13
        13b7:       41 54                   push   %r12
        13b9:       41 89 fc                mov    %edi,%r12d
        13bc:       55                      push   %rbp
        13bd:       48 8d 2d b4 29 00 00    lea    0x29b4(%rip),%rbp        # 3d78 <__do_global_dtors_aux_fini_array_entry>
        13c4:       53                      push   %rbx
        13c5:       4c 29 fd                sub    %r15,%rbp
        13c8:       48 83 ec 08             sub    $0x8,%rsp
        13cc:       e8 2f fc ff ff          callq  1000 <_init>
        13d1:       48 c1 fd 03             sar    $0x3,%rbp
        13d5:       74 1f                   je     13f6 <__libc_csu_init+0x56>
        13d7:       31 db                   xor    %ebx,%ebx
        13d9:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
        13e0:       4c 89 f2                mov    %r14,%rdx
        13e3:       4c 89 ee                mov    %r13,%rsi
        13e6:       44 89 e7                mov    %r12d,%edi
        13e9:       41 ff 14 df             callq  *(%r15,%rbx,8)
        13ed:       48 83 c3 01             add    $0x1,%rbx
        13f1:       48 39 dd                cmp    %rbx,%rbp
        13f4:       75 ea                   jne    13e0 <__libc_csu_init+0x40>
        13f6:       48 83 c4 08             add    $0x8,%rsp
        13fa:       5b                      pop    %rbx
        13fb:       5d                      pop    %rbp
        13fc:       41 5c                   pop    %r12
        13fe:       41 5d                   pop    %r13
        1400:       41 5e                   pop    %r14
        1402:       41 5f                   pop    %r15
        1404:       c3                      retq   
        1405:       66 66 2e 0f 1f 84 00    data16 nopw %cs:0x0(%rax,%rax,1)
        140c:       00 00 00 00 
    

    光看汇编代码有点难以理解,我们可以去查看glibc的源代码中的__libc_csu_init函数,其中关键代码部分:

    void __libc_csu_init (int argc, char **argv, char **envp){
    ...
    const size_t size = __init_array_end - __init_array_start;
      for (size_t i = 0; i < size; i++)
          (*__init_array_start [i]) (argc, argv, envp);     //事实上这个__init_array_satrt数组中就有全局对象构造函数的地址
    }
    ...
    }
    

    可以看出,__ libc_csu_init函数中会将__init_array_start数组中每个指针指向的函数执行一遍。

    现在回到原来的问题,负责本编译单元所有全局\静态对象的构造和析构的_GLOBAL__sub_I_o1函数的指针被保存在__init_array_start数组中,也就是在__libc_csu_init函数中被调用的。

    那么_GLOBAL__sub_I_o1函数的指针怎么被放进 __ init_array_start数组的呢?答案是,一旦一个目标文件里有一个这样的函数,编译器会在这个编译单元产生的目标文件(.o)文件的“.init_array”段中放置一个指针,这个指针指向的就是_GLOBAL__sub_I_a1函数。

    //objdump -s 
    ......
    Contents of section .init_array:
     600dc8 b0054000 00000000 2d064000 00000000  ..@.....-.@.....
    ......
    
    

    析构

    在__lib_start_main 函数执行完main函数之后,执行exit函数:

    void exit(int status){
        while(__exit_func != NULL){
            ...
            __exit_funcs = __exit_funcs->next;      //__exit_funcs是存储由_cxa_atexit组成的函数的链表,
                                                    //这里的while循环则遍历该链表并逐个调用这些注册的函数    
        }
        ...
        _exit(status);                              //调用exit系统调用,进程直接结束
    }
    

    总结

    --->_start

    ​ --->_lib_start_main

    ​ --->__ libc_csu_init

    ​ --->main

    ​ --->__libc_csu_fini

    _start
    ---> _libc_start_main    
    ------> _libc_csu_init
    ---------> _GLOBAL__sub_I_o1
    ------------> _Z41__static_initialization_and_destruction_0ii
    ---------------> _ZN6ObjectC1Ei  #全局构造函数
    ------> main                #main函数
    ------> exit
    ---------> _ZN6ObjectD1Ev        #全局析构函数
    
    
  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6