c++ - 为什么汇编输出中有这么多 iostream 的样板文件?

标签 c++ gcc assembly

对于以下代码:

int main()
{
}

对于g++ -pedantic -Wall -O3 -S -o test.asm test.cpp && cat test.asm , assembly 输出毫无疑问是干净的。如果我这样做gcc -x c ... test c#include <stdio.h>在顶部,除了标签名称之外,输出相同。其实是否在 C++ 中并不重要或C模式。其他 header 如 <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>特别吗?

可能相关的一个引用是:

In terms of static initialization order, cout is guaranteed to be properly constructed and initialized no later than the first time an object of type ios_base::Init is constructed, with the inclusion of counting as at least one initialization of such objects with static duration.

最佳答案

这个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
} 

相关引用:

Now, the runtime penalty mentioned previously: the global objects must be initialized before any of your own code uses them; this is guaranteed by the standard. Like any other global object, they must be initialized once and only once. This is typically done with a construct like the one above, and the nested class ios_base::Init is specified in the standard for just this reason.

还有standard quote :

According to §27.3/2: "The objects [std::cin, std::cout, etc.] are constructed, and the associations are established at some time prior to or during first time an object of class ios_base::Init is constructed, and in any case before the body of main begins execution."

罪魁祸首确实是 ios_base::Init行,如cHao的评论表明。因此,如果 msdn 链接正确,则意味着 <iostream>special因此。

关于c++ - 为什么汇编输出中有这么多 iostream 的样板文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20779400/

相关文章:

c++ - 在构建时以通用方式将功能附加到类

gcc - 在 g++ linux 中找不到 -lc 和 -lm

c++ - 在 C++ 11 中使用 Homebrew 软件、gcc 和 llvm

c++ - Intel TBB 使用task_group 进行双调排序

c++ - 非模板错误的模板定义

r - 在 linux 中为 R 安装 xgboost 时出错

java - 压入和弹出整数到堆栈,什么结果是不可能的

assembly - 在 ti 84+ 上的 ti 基本程序中使用十六进制代码

assembly - 优化这个汇编代码

c++ - OpenglES 2.0 顶点着色器属性