代码之家  ›  专栏  ›  技术社区  ›  Klaus

我也看到了很多未使用和剥离的函数的全局子函数,如何删除它们

  •  2
  • Klaus  · 技术社区  · 6 年前

    有一个非常小的项目:

    功能c2.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 功能仍然存在。我怎样才能移除它们?

    在我看来,IOstream对象的每个用户 cout 将生成其他初始值设定项函数。有什么办法可以摆脱它吗?我觉得每个可执行文件只需要一次,但我看到了多次。一般来说,如何避免?

    1 回复  |  直到 6 年前
        1
  •  3
  •   Bo Persson Touseef    6 年前

    罪魁祸首是 std::ios_base::Init::Init() 从每个包含 <iostream> .调用保证流在第一次使用前正确初始化。

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