包含iostream导致不同的二进制文件
Include of iostream leads to different binary
编译以下代码
int main() {
return 0;
}
给程序集
main:
xorl %eax, %eax
ret
https://gcc.godbolt.org/z/oQvRDd
如果现在包括iostream
#include <iostream>
int main() {
return 0;
}
将创建此程序集。
main:
xorl %eax, %eax
ret
_GLOBAL__sub_I_main:
subq $8, %rsp
movl $_ZStL8__ioinit, %edi
call std::ios_base::Init::Init() [complete object constructor]
movl $__dso_handle, %edx
movl $_ZStL8__ioinit, %esi
movl $_ZNSt8ios_base4InitD1Ev, %edi
addq $8, %rsp
jmp __cxa_atexit
完全优化已打开 (-O3(。 https://gcc.godbolt.org/z/EtrEX8
有人可以解释一下,为什么包含未使用的标头会更改二进制文件。什么是_GLOBAL__sub_I_main:
?
包含<iostream>
的每个翻译单元都包含ios_base::Init
对象的副本:
static ios_base::Init __ioinit;
此对象用于初始化标准流(std::cout
及其友元(。此方法称为 Schwarz 计数器,它确保标准流始终在首次使用之前进行初始化(前提是已包含iostream
标头(。
该函数_GLOBAL__sub_I_main
是编译器为每个翻译单元生成的代码,该转换单元调用该转换单元中全局对象的构造函数,并安排在退出时调用相应的析构函数调用。在调用main
之前,此代码由C++标准库启动代码调用。
包含iostream
标头具有添加静态std::ios_base::Init
对象定义的效果。此静态对象的构造函数初始化标准流对象std::cout
、std::cerr
等。
这样做的原因是为了避免静态初始化顺序惨败。它确保跨翻译单元正确初始化流对象。
相关文章:
- 正在读取二进制文件(is_open)
- 在C++中将类(带有Vector成员)保存为二进制文件
- 如何从二进制文件中读取字符串
- 保存/加载大量短数组到二进制文件
- 从二进制文件中读取整数数组
- Android 在编译二进制文件时重建静态库
- 在 C++ 中将双精度变量写入二进制文件
- clang 的 libFuzzer 可以在同一二进制文件中测试超过 1 个 API 吗?
- C++:实际上不是从二进制文件中读取
- 如何从二进制文件中的给定符号中获取调用程序图
- 将内部带有矢量的结构保存/读取到二进制文件中
- 编译多个C++文件.调用二进制文件以运行代码
- 如何使用位字段将数据从二进制文件复制到结构中?
- uint8_t同一二进制文件的不同十进制值
- C++单个生成文件多个二进制文件
- 尝试将数字写入二进制文件时引发异常
- C++中读/写二进制文件
- 如何忽略某些二进制文件的执行?
- 包含iostream导致不同的二进制文件
- G++ 为什么你不必链接 iostream 二进制文件,但对于 pthread,你这样做了?