c ++的构造函数和析构函数汇编[重复]

Posted

技术标签:

【中文标题】c ++的构造函数和析构函数汇编[重复]【英文标题】:Constructor and destructor assembly of c++ [duplicate] 【发布时间】:2013-11-25 18:37:24 【问题描述】:

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

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

    __ZN13trivialStructC1Ev: ## @_ZN13trivialStructC1Ev __ZN13trivialStructC2Ev: ## @_ZN13trivialStructC2Ev __ZN13trivialStructD1Ev: ## @_ZN13trivialStructD1Ev __ZN13trivialStructD2Ev: ## @_ZN13trivialStructD2Ev

我不知道为什么编译器会生成两部分代码,而不仅仅是一部分? 我不熟悉汇编,但看起来这只是让代码变成 更胖(也许更慢)。

【问题讨论】:

尝试优化代码的大小(将-Os 传递给g++)。此外,更少的代码并不总是更好 - 分支可能非常昂贵。 请注意,代码不会变慢。如果不使用构造函数,链接器可能会删除符号(阅读链接器的文档),即使它们没有被删除,它们也会占用内存中的一些空间,但永远不会被评估(即不会导致其他代码被逐出缓存)。 【参考方案1】:

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

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

不同的符号承担的职责略有不同,因为实现可能需要根据对象的创建/销毁方式执行不同的操作。在您的特定情况下,代码非常简单,所有构造函数都可能生成完全相同的代码,但它们需要存在以符合 ABI,并且 ABI 具有它们以支持更复杂的用例。

例如,一个完整的对象构造函数会初始化虚基,而基对象构造函数会跳过这部分构造。如果存在多重/虚拟继承和虚函数,则完整对象中的 vptr 可能必须根据子对象的实例化方式来跳过不同的中间表集。

如果您想要ABI 要求以外的其他解释,您应该查看特定 ABI 的文档。您还可以查看C++ 对象模型的内部,即使它是旧的,也包含对要解决的问题和提供的一些解决方案的良好描述。

【讨论】:

以上是关于c ++的构造函数和析构函数汇编[重复]的主要内容,如果未能解决你的问题,请参考以下文章

php构造函数的PHP 5 构造函数和析构函数

c++ 复制构造函数和析构函数

[类和对象]构造和析构

C++构造和析构

我需要在新类中声明构造函数和析构函数吗?

c++中构造和析构函数