【问题标题】:Purpose of static_initialization_and_destruction and _GLOBAL__sub_I_main function in the assembly code for a C++ code?C++ 代码的汇编代码中 static_initialization_and_destruction 和 _GLOBAL__sub_I_main 函数的用途?
【发布时间】:2016-09-03 15:20:39
【问题描述】:

以下是 C++ 源代码。该代码有一个类 HumanBeing 并具有显示和验证功能。每个函数都打印语句。

#include <iostream>

using namespace std;

class HumanBeing {
public:
    void display() {
        cout << "hello aam a human being" << endl;
    }
    void print() {
        cout << "verify print" << endl;
    }
};

int main() {
    HumanBeing vamshi;

    vamshi.display();
    vamshi.print();
    return 0;
}

这是上面c++代码对应的汇编代码

        .file   "verify.cpp"
        .local  _ZStL8__ioinit
        .comm   _ZStL8__ioinit,1,1
        .section        .rodata
.LC0:
        .string "hello aam a human being"
        .section        .text._ZN10HumanBeing7displayEv,"axG",@progbits,_ZN10HumanBeing7displayEv,comdat
        .align 2
        .weak   _ZN10HumanBeing7displayEv
        .type   _ZN10HumanBeing7displayEv, @function
_ZN10HumanBeing7displayEv:
.LFB971:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $16, %rsp
        movq    %rdi, -8(%rbp)
        movl    $.LC0, %esi
        movl    $_ZSt4cout, %edi
        call    _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
        movl    $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, %esi
        movq    %rax, %rdi
        call    _ZNSolsEPFRSoS_E
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE971:
        .size   _ZN10HumanBeing7displayEv, .-_ZN10HumanBeing7displayEv
        .section        .rodata
.LC1:
        .string "verify print"
        .section        .text._ZN10HumanBeing5printEv,"axG",@progbits,_ZN10HumanBeing5printEv,comdat
        .align 2
        .weak   _ZN10HumanBeing5printEv
        .type   _ZN10HumanBeing5printEv, @function
_ZN10HumanBeing5printEv:
.LFB972:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $16, %rsp
        movq    %rdi, -8(%rbp)
        movl    $.LC1, %esi
        movl    $_ZSt4cout, %edi
        call    _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
        movl    $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, %esi
        movq    %rax, %rdi
        call    _ZNSolsEPFRSoS_E
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE972:
        .size   _ZN10HumanBeing5printEv, .-_ZN10HumanBeing5printEv
        .text
        .globl  main
        .type   main, @function
main:
.LFB973:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $16, %rsp
        leaq    -1(%rbp), %rax
        movq    %rax, %rdi
        call    _ZN10HumanBeing7displayEv
        leaq    -1(%rbp), %rax
        movq    %rax, %rdi
        call    _ZN10HumanBeing5printEv
        movl    $0, %eax
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE973:
        .size   main, .-main
        .type   _Z41__static_initialization_and_destruction_0ii, @function
_Z41__static_initialization_and_destruction_0ii:
.LFB982:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $16, %rsp
        movl    %edi, -4(%rbp)
        movl    %esi, -8(%rbp)
        cmpl    $1, -4(%rbp)
        jne     .L5
        cmpl    $65535, -8(%rbp)
        jne     .L5
        movl    $_ZStL8__ioinit, %edi
        call    _ZNSt8ios_base4InitC1Ev
        movl    $__dso_handle, %edx
        movl    $_ZStL8__ioinit, %esi
        movl    $_ZNSt8ios_base4InitD1Ev, %edi
        call    __cxa_atexit
.L5:
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE982:
        .size   _Z41__static_initialization_and_destruction_0ii, .-_Z41__static_initialization_and_destruction_0ii
        .type   _GLOBAL__sub_I_main, @function
_GLOBAL__sub_I_main:
.LFB983:
        .cfi_startproc

在这段代码中我有以下疑惑:

1.static_initialization_and_destruction -- 似乎是函数,但它的具体工作原理并不清楚

  1. GLOBAL__sub_I_main 函数的用途和工作方式尚不清楚。

谁能清楚地解释这段代码中构造函数和析构函数的工作和组织以及 GLOBAL__sub_I_main 函数的用途?

【问题讨论】:

    标签: assembly constructor destructor


    【解决方案1】:

    这两个函数都被 C++ 中的 gcc 用于任何需要在 main 之前构建的具有静态存储持续时间的实例化类,例如

    class A {
        A();
        ~A();
        ... 
    };
    
    A a;
    
    // "a" will need to be constructed before main
    int main()
    {
        return a.Foo();
    }
    // "a" will need to be destructed after main
    

    生成的_Z41__static_initialization_and_destruction_0ii 函数(解构__static_initialization_and_destruction_0(int, int))有两个用途:

    • 在预处理/编译的 C++ 源文件中调用任何具有静态存储持续时间的类的构造函数(如果需要)
    • 通过atexit 在预处理/编译的 C++ 源文件(如果需要)中将具有静态存储持续时间的类的析构函数注册为退出函数。

    _GLOBAL__sub_I_main 是一个简单的包装函数,它的函数指针被添加到.init_array 部分。编译多个源文件时,每个单独的目标文件都会向.init_array 添加初始化函数,并且所有这些函数都将在调用main 之前调用。

    虽然这可能不是很明显,但您的代码包含具有静态存储持续时间的实例。 &lt;iostream&gt; 头文件声明了std::ios_base::Init 需要尽早构造,以确保在静态对象的构造函数和析构函数中访问标准 I/O 流是安全的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-27
      • 2014-11-30
      • 2021-07-18
      • 1970-01-01
      • 1970-01-01
      • 2015-04-27
      • 2016-08-27
      • 2013-03-13
      相关资源
      最近更新 更多