c ++的构造函数和析构函数程序集

时间:2013-11-25 18:37:24

标签: c++ assembly

c ++代码

#include <cstdio>
#include <cstdlib>

struct trivialStruct
{        

trivialStruct();
~trivialStruct();

int *a;
float *b;
float *c;

};

trivialStruct::trivialStruct() : a((int*)malloc(sizeof(int))), b((float*)malloc(sizeof(float))), c((float*)malloc(sizeof(float)))
{
  *a = 100;
  *b = 200;
  *c = 300;
}

trivialStruct::~trivialStruct()
{
  free(a);
  free(b);
  free(c);

  a = nullptr;
  b = nullptr;
  c = nullptr;
}

int main()
{
  trivialStruct A;
  printf("%d, %f, %f", *A.a, *A.b, *A.c);

  return 0;
}

组件

.section    __TEXT,__text,regular,pure_instructions
    .globl  __ZN13trivialStructC1Ev
    .align  4, 0x90
__ZN13trivialStructC1Ev:                ## @_ZN13trivialStructC1Ev
    .cfi_startproc
## BB#0:                                ## %entry
    push    RBP
Ltmp3:
    .cfi_def_cfa_offset 16
Ltmp4:
    .cfi_offset rbp, -16
    mov RBP, RSP
Ltmp5:
    .cfi_def_cfa_register rbp
    push    R15
    push    R14
    push    RBX
    push    RAX
Ltmp6:
    .cfi_offset rbx, -40
Ltmp7:
    .cfi_offset r14, -32
Ltmp8:
    .cfi_offset r15, -24
    mov RBX, RDI
    mov EDI, 4
    call    _malloc
    mov R14, RAX
    mov QWORD PTR [RBX], R14
    mov EDI, 4
    call    _malloc
    mov R15, RAX
    mov QWORD PTR [RBX + 8], R15
    mov EDI, 4
    call    _malloc
    mov QWORD PTR [RBX + 16], RAX
    mov DWORD PTR [R14], 100
    mov DWORD PTR [R15], 1128792064
    mov DWORD PTR [RAX], 1133903872
    add RSP, 8
    pop RBX
    pop R14
    pop R15
    pop RBP
    ret
    .cfi_endproc

    .globl  __ZN13trivialStructC2Ev
    .align  4, 0x90
__ZN13trivialStructC2Ev:                ## @_ZN13trivialStructC2Ev
    .cfi_startproc
## BB#0:                                ## %entry
    push    RBP
Ltmp12:
    .cfi_def_cfa_offset 16
Ltmp13:
    .cfi_offset rbp, -16
    mov RBP, RSP
Ltmp14:
    .cfi_def_cfa_register rbp
    push    R15
    push    R14
    push    RBX
    push    RAX
Ltmp15:
    .cfi_offset rbx, -40
Ltmp16:
    .cfi_offset r14, -32
Ltmp17:
    .cfi_offset r15, -24
    mov RBX, RDI
    mov EDI, 4
    call    _malloc
    mov R14, RAX
    mov QWORD PTR [RBX], R14
    mov EDI, 4
    call    _malloc
    mov R15, RAX
    mov QWORD PTR [RBX + 8], R15
    mov EDI, 4
    call    _malloc
    mov QWORD PTR [RBX + 16], RAX
    mov DWORD PTR [R14], 100
    mov DWORD PTR [R15], 1128792064
    mov DWORD PTR [RAX], 1133903872
    add RSP, 8
    pop RBX
    pop R14
    pop R15
    pop RBP
    ret
    .cfi_endproc

    .globl  __ZN13trivialStructD1Ev
    .align  4, 0x90
__ZN13trivialStructD1Ev:                ## @_ZN13trivialStructD1Ev
    .cfi_startproc
## BB#0:                                ## %entry
    push    RBP
Ltmp21:
    .cfi_def_cfa_offset 16
Ltmp22:
    .cfi_offset rbp, -16
    mov RBP, RSP
Ltmp23:
    .cfi_def_cfa_register rbp
    push    RBX
    push    RAX
Ltmp24:
    .cfi_offset rbx, -24
    mov RBX, RDI
    mov RDI, QWORD PTR [RBX]
    call    _free
    mov RDI, QWORD PTR [RBX + 8]
    call    _free
    mov RDI, QWORD PTR [RBX + 16]
    call    _free
    mov QWORD PTR [RBX + 16], 0
    mov QWORD PTR [RBX + 8], 0
    mov QWORD PTR [RBX], 0
    add RSP, 8
    pop RBX
    pop RBP
    ret
    .cfi_endproc

    .globl  __ZN13trivialStructD2Ev
    .align  4, 0x90
__ZN13trivialStructD2Ev:                ## @_ZN13trivialStructD2Ev
    .cfi_startproc
## BB#0:                                ## %entry
    push    RBP
Ltmp28:
    .cfi_def_cfa_offset 16
Ltmp29:
    .cfi_offset rbp, -16
    mov RBP, RSP
Ltmp30:
    .cfi_def_cfa_register rbp
    push    RBX
    push    RAX
Ltmp31:
    .cfi_offset rbx, -24
    mov RBX, RDI
    mov RDI, QWORD PTR [RBX]
    call    _free
    mov RDI, QWORD PTR [RBX + 8]
    call    _free
    mov RDI, QWORD PTR [RBX + 16]
    call    _free
    mov QWORD PTR [RBX + 16], 0
    mov QWORD PTR [RBX + 8], 0
    mov QWORD PTR [RBX], 0
    add RSP, 8
    pop RBX
    pop RBP
    ret
    .cfi_endproc

    .section    __TEXT,__literal8,8byte_literals
    .align  3
LCPI4_0:
    .quad   4641240890982006784     ## double 200
LCPI4_1:
    .quad   4643985272004935680     ## double 300
    .section    __TEXT,__text,regular,pure_instructions
    .globl  _main
    .align  4, 0x90
_main:                                  ## @main
    .cfi_startproc
## BB#0:                                ## %entry
    push    RBP
Ltmp34:
    .cfi_def_cfa_offset 16
Ltmp35:
    .cfi_offset rbp, -16
    mov RBP, RSP
Ltmp36:
    .cfi_def_cfa_register rbp
    lea RDI, QWORD PTR [RIP + L_.str]
    movsd   XMM0, QWORD PTR [RIP + LCPI4_0]
    movsd   XMM1, QWORD PTR [RIP + LCPI4_1]
    mov ESI, 100
    mov AL, 2
    call    _printf
    xor EAX, EAX
    pop RBP
    ret
    .cfi_endproc

    .section    __TEXT,__cstring,cstring_literals
L_.str:                                 ## @.str
    .asciz   "%d, %f, %f"


.subsections_via_symbols

命令 clang ++ -S -O2 -std = c ++ 11 -mllvm --x86-asm-syntax = intel -fno-exceptions main.cpp

如您所见,代码的两部分是相同的(构造函数和析构函数)

  1. __ ZN13trivialStructC1Ev:## @ _ZN13trivialStructC1Ev
  2. __ ZN13trivialStructC2Ev:## @ _ZN13trivialStructC2Ev
  3. __ ZN13trivialStructD1Ev:## @ _ZN13trivialStructD1Ev
  4. __ ZN13trivialStructD2Ev:## @ _ZN13trivialStructD2Ev
  5. 我不知道为什么编译器生成两部分代码而不只是一部分? 我不熟悉汇编,但看起来这只是使代码成为 更胖(也许更慢)。

1 个答案:

答案 0 :(得分:3)

这是您平台的ABI的一部分,并且不符合标准。构造函数和析构函数都可以在二进制文件中生成多个符号。例如,Itanium C ++ ABI将生成最多3个构造函数/析构函数:

  • 完整对象构造函数
  • 基础对象构造函数
  • 完整对象分配构造函数
  • 删除析构函数
  • 完整对象析构函数
  • 基础对象析构函数

不同的符号承担略有不同的职责,因为实现可能需要根据对象的创建/销毁方式做不同的事情。在您的特定情况下,代码很简单,所有构造函数可能生成完全相同的代码,但它们需要符合ABI,ABI使它们能够实现更复杂的用例。

例如,完整的对象构造函数将初始化虚拟基础,而基础对象构造函数将跳过此部分构造。如果存在多个/虚拟继承和虚函数,则完整对象中的vptr可能必须跳过不同的中间表集,具体取决于该子对象的实例化方式。

如果您想要除 ABI强制要求以外的解释,您应该查看特定ABI的文档。您还可以查看 Inside C ++对象模型,即使是旧的,也包含对要解决的问题的详细描述以及提供的一些解决方案。