来自其他链接单元的垃圾

Umm*_*mma 5 c++ optimization linker

当我讨论这个话题时,我问自己以下问题。

是否存在翻译单元中一些未使用的代码将链接到 GCC 和 VC++ 等流行编译器的最终可执行代码(当然是在发布模式下)的情况?

例如假设我们有 2 个编译单元:

//A.hpp
//Here are declarations of some classes, functions, extern variables etc.
Run Code Online (Sandbox Code Playgroud)

以及源文件

//A.cpp
//defination of A.hpp declarations
Run Code Online (Sandbox Code Playgroud)

最后是主要的

//main.cpp
//including A.hpp library
#include "A.hpp"
//here we will use some stuff from A.hpp library, but not everything
Run Code Online (Sandbox Code Playgroud)

我的问题是。如果 main.cpp 中没有使用 A.hpp 中的所有内容怎么办?链接器是否会删除所有未使用的代码,或者在某些情况下,某些未使用的代码可以与可执行文件链接?

编辑:我对 G++ 和 VC++ 链接器感兴趣。

编辑:当然我的意思是在发布模式下。

编辑:我开始为这个问题提供赏金,以获得良好而完整的答案。我期待答案,它将解释在哪些情况下 g++ 和 VC++ 链接器链接垃圾以及它们能够从可执行文件中删除什么样的代码(不需要的函数、不需要的全局变量、不需要的类定义等...)以及为什么他们不能删除一些不需要的东西。

J T*_*J T 5

正如其他发帖者所指出的,链接器通常不会在构建最终可执行文件之前删除死代码。但是,您通常可以使用优化设置来强制链接器更加努力地执行此操作。

对于 GCC,这分两个阶段完成:

  1. 首先编译数据,但告诉编译器将代码分成翻译单元内的单独部分。这将通过使用以下两个编译器标志对函数、类和外部变量完成:

    -fdata-sections -ffunction-sections

  2. 使用链接器优化标志将翻译单元链接在一起(这会导致链接器丢弃未引用的部分):

    -Wl,--gc-部分

因此,如果您有一个名为 test.cpp 的文件,其中声明了两个函数,但其​​中之一未使用,则可以使用 gcc(g++) 的以下命令省略未使用的函数:

gcc -Os -fdata-sections -ffunction-sections test.cpp -o test.o -Wl,--gc-sections
Run Code Online (Sandbox Code Playgroud)

(请注意,-Os 是一个附加的链接器标志,告诉 GCC 优化大小)

我还在某处读到链接静态库是不同的。在这种情况下,GCC 会自动忽略未使用的符号。也许另一张海报可以证实/反驳这一点。

至于 MSVC,正如其他人提到的,功能级链接完成同样的事情。我相信编译器标志是(将内容分类为部分):

/Gy
Run Code Online (Sandbox Code Playgroud)

然后是链接器标志(丢弃未使用的部分):

/OPT:REF
Run Code Online (Sandbox Code Playgroud)

编辑:经过进一步的研究,我认为关于 GCC 自动为静态库执行此操作的说法是错误的。