c++ - 我看到很多 _GLOBAL__sub_I__ 也来自未使用和剥离的函数,如何删除它们

标签 c++ ld

有那个非常小的项目:

func2.cpp:

#include <iostream>

void myfunc2()
{
    std::cout << "Func2 called" << std::endl;
}

函数.cpp:

#include <iostream>
#include "func.h"

void myfunc()
{
    std::cout << "Hallo func " << std::endl;
}

主要.cpp:

#include "func.h"
#include "func2.h"

int main()
{
    //myfunc();  // intentionally moved away!
    //myfunc2();
}

.h 文件只有所需函数的定义。

生成文件:

all: go

%.o: %.cpp
    g++ -O3 -fdata-sections -ffunction-sections $< -c

go: main.o func.h func.o func2.o func2.h
    g++ -fdata-sections -ffunction-sections main.o func.o func2.o -o go -Wl,--gc-sections

如果我对生成的可执行文件进行反汇编,我仍然有两个不需要的函数:

0000000000400560 <_GLOBAL__sub_I__Z6myfuncv>:
  400560:   48 83 ec 08             sub    $0x8,%rsp
  400564:   bf 31 10 60 00          mov    $0x601031,%edi
  400569:   e8 c2 ff ff ff          callq  400530 <std::ios_base::Init::Init()@plt>
  40056e:   ba 30 07 40 00          mov    $0x400730,%edx
  400573:   be 31 10 60 00          mov    $0x601031,%esi
  400578:   bf 40 05 40 00          mov    $0x400540,%edi
  40057d:   48 83 c4 08             add    $0x8,%rsp
  400581:   e9 9a ff ff ff          jmpq   400520 <__cxa_atexit@plt>
  400586:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  40058d:   00 00 00  

0000000000400590 <_GLOBAL__sub_I__Z7myfunc2v>:
  400590:   48 83 ec 08             sub    $0x8,%rsp
  400594:   bf 32 10 60 00          mov    $0x601032,%edi
  400599:   e8 92 ff ff ff          callq  400530 <std::ios_base::Init::Init()@plt>
  40059e:   ba 30 07 40 00          mov    $0x400730,%edx
  4005a3:   be 32 10 60 00          mov    $0x601032,%esi
  4005a8:   bf 40 05 40 00          mov    $0x400540,%edi
  4005ad:   48 83 c4 08             add    $0x8,%rsp
  4005b1:   e9 6a ff ff ff          jmpq   400520 <__cxa_atexit@plt>
  4005b6:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  4005bd:   00 00 00  

看起来每个需要 iostream 对象的文件都会生成一个在初始化期间调用的函数。该部分和生成的函数从该文件中第一个定义的函数中获取名称。

如果我不使用那个函数并且它没有链接到最终的可执行文件中,这些 _GLOBAL__sub_I__xxxx 函数仍然存在。我怎样才能删除它们?

在我看来,像 cout 这样的 iostream 对象的每个用户都会生成一个额外的初始化函数,这对我来说非常神秘。有什么技巧可以摆脱它吗?我觉得每个可执行文件只需要一次,但我多次看到它。一般如何避免?

最佳答案

罪魁祸首是 std::ios_base::Init::Init() 从包含 <iostream> 的每个源文件调用的构造函数.该调用保证在首次使用前正确初始化流。

并且由于 "static initialization order fiasco"这种初始化必须出现在所有可能使用流的文件中,因为我们不知道不同源文件之间的初始化顺序。

关于c++ - 我看到很多 _GLOBAL__sub_I__ 也来自未使用和剥离的函数,如何删除它们,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51262869/

相关文章:

c++ - Vulkan UBO 传递错误

c - ld 返回 1 退出状态,斐波那契搜索

linux - 使用printf和ld链接程序?

assembly - GNU 程序集引导加载程序无法引导

c - 如何将 C 目标文件与汇编语言目标文件链接起来?

c++ - gethostbyname 创建一个线程?

c++ - 如何解决有关字 rune 字的 C4428 Visual C++ 警告的此实例?

c++ - 使用多重链接树释放内存时遇到问题

c++ - 由于多个 'main',STM8上的cpputest失败

c++ - 使用 CMake 从二进制文件编译和添加目标文件