为什么装配输出中有iostream的样板?

时间:2013-12-26 05:03:10

标签: c++ gcc assembly

以下代码:

int main()
{
}

对于g++ -pedantic -Wall -O3 -S -o test.asm test.cpp && cat test.asm,程序集输出不出所料。如果我在顶部gcc -x c ... test c #include <stdio.h>,则输出相同,但标签名称除外。实际上,如果它处于C++C模式并不重要。其他标题如<string><vector><algorithm><ostream>等会产生相同的结果。

    .file   "test.cpp"
    .section    .text.unlikely,"ax",@progbits
.LCOLDB0:
    .section    .text.startup,"ax",@progbits
.LHOTB0:
    .p2align 4,,15
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    xorl    %eax, %eax
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .section    .text.unlikely
.LCOLDE0:
    .section    .text.startup
.LHOTE0:
    .ident  "GCC: (GNU) 4.9.0 20131223 (experimental)"
    .section    .note.GNU-stack,"",@progbits

但是只要你添加#include <iostream>,它就会爆炸(省略相同的部分):

    .section    .text.unlikely
.LCOLDE0:
    .section    .text.startup
.LHOTE0:
    .section    .text.unlikely
.LCOLDB1:
    .section    .text.startup
.LHOTB1:
    .p2align 4,,15
    .type   _GLOBAL__sub_I_main, @function
_GLOBAL__sub_I_main:
.LFB1027:
    .cfi_startproc
    subq    $8, %rsp
    .cfi_def_cfa_offset 16
    movl    $_ZStL8__ioinit, %edi
    call    _ZNSt8ios_base4InitC1Ev
    movl    $__dso_handle, %edx
    movl    $_ZStL8__ioinit, %esi
    movl    $_ZNSt8ios_base4InitD1Ev, %edi
    addq    $8, %rsp
    .cfi_def_cfa_offset 8
    jmp __cxa_atexit
    .cfi_endproc
.LFE1027:
    .size   _GLOBAL__sub_I_main, .-_GLOBAL__sub_I_main
    .section    .text.unlikely
.LCOLDE1:
    .section    .text.startup
.LHOTE1:
    .section    .init_array,"aw"
    .align 8
    .quad   _GLOBAL__sub_I_main
    .local  _ZStL8__ioinit
    .comm   _ZStL8__ioinit,1,1
    .hidden __dso_handle
    .ident  "GCC: (GNU) 4.9.0 20131223 (experimental)"
    .section    .note.GNU-stack,"",@progbits

是什么让<iostream>特别?

可能相关的一个引用是:

  

就静态初始化顺序而言,cout是保证的   不迟于第一次正确构建和初始化   构造ios_base :: Init类型的对象,包含    计为至少一次这种对象的初始化   静态持续时间。

1 个答案:

答案 0 :(得分:2)

MSDN forum link提供了一个代码段:

#include <ostream>
#include <istream>

namespace std
{
    extern istream cin;
    extern ostream cout;
    ....

    // this is explained below
    static ios_base::Init __foo;    // not its real name
} 

相关引用:

  

现在,前面提到的运行时惩罚:全局对象必须   在您自己的代码使用它们之前进行初始化;这是   由标准保证。像任何其他全球对象一样,它们必须如此   初始化一次且仅一次。这通常用a来完成   像上面那样构造,嵌套类ios_base :: Init是   由于这个原因,在标准中规定了。

standard quote

  

根据§27.3/ 2:“对象[std :: cin,std :: cout等]是   构建,并在之前的某个时间建立协会   到或在第一次使用类ios_base :: Init的对象时   构造,并且无论如何在主体开始之前   执行“。

罪魁祸首确实是ios_base::Init行,正如cHao的评论所暗示的那样。因此,如果msdn链接正确,则表示<iostream>因此special为{{3}}。