编译以下代码

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

有人可以解释一下,为什么包括未使用的 header 会更改二进制文件。什么是_GLOBAL__sub_I_main:

最佳答案

每个包含<iostream>的翻译单元都包含ios_base::Init对象的副本:

static ios_base::Init __ioinit;

该对象用于初始化标准流(std::cout及其 friend )。此方法称为Schwarz Counter,它确保标准流始终在首次使用之前进行初始化(已提供了iostream header )。

该函数_GLOBAL__sub_I_main是编译器为每个翻译单元生成的代码,该代码调用该翻译单元中的全局对象的构造函数,并安排在导出处调用相应的析构函数调用。在调用main之前,此代码由C++标准库启动代码调用。

关于c++ - 包含iostream导致不同的二进制文件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52079248/

10-13 08:28