为啥在汇编输出中有这么多 iostream 样板文件?
Posted
技术标签:
【中文标题】为啥在汇编输出中有这么多 iostream 样板文件?【英文标题】:Why so much boilerplate for iostream in assembly output?为什么在汇编输出中有这么多 iostream 样板文件? 【发布时间】:2013-12-26 05:03:10 【问题描述】:对于以下代码:
int main()
对于g++ -pedantic -Wall -O3 -S -o test.asm test.cpp && cat test.asm
,程序集输出干净利落。如果我在顶部使用 gcc -x c ... test c
和 #include <stdio.h>
,则输出是 identical 除了标签名称。其实不管是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 类型的对象,其中包含 算作此类对象的至少一次初始化 具有静态持续时间。
【问题讨论】:
我想知道如果您实际实例化并使用了流,您是否会得到与<ostream>
相同的结果。
你的报价没有回答你的问题吗?
@JonathonReinhart 是的,我想是的,但直到我用谷歌搜索后我才知道为什么。
【参考方案1】:
这个MSDN forum link提供了一个代码sn-p:
#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
相关引述:
现在,前面提到的运行时惩罚:全局对象必须 在您自己的任何代码使用它们之前进行初始化;这是 由标准保证。像任何其他全局对象一样,它们必须是 初始化一次且仅一次。这通常是用一个 像上面那样构造,嵌套类 ios_base::Init 是 正是出于这个原因在标准中指定。
还有standard quote:
根据 §27.3/2:“对象 [std::cin, std::cout, etc.] 是 构建,并且协会是在某个时间之前建立的 到或在第一次类 ios_base::Init 的对象是 构造,并且无论如何在 main 的主体开始之前 执行。”
罪魁祸首确实是ios_base::Init
行,正如cHao 的评论所暗示的那样。因此,如果 msdn 链接正确,则意味着 <iostream>
是 special。
【讨论】:
以上是关于为啥在汇编输出中有这么多 iostream 样板文件?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 OPENCV 中有这么多函数使用 InputArray 和 OutputArray 作为函数参数?