2011-06-02 71 views

回答

3

相当多的时间,是的。它通常被称为链接器剥离。

-2

这一切都取决于编译器及其设置(内置“调试”配置的代码通常未优化),以及代码本身和行星对齐。

潜在的问题是:你不应该担心那些东西。相信你的编译器。

+2

如果您有一些外部要求,即可执行文件包含某个未使用的符号,则必须担心。没有得到解决。 – 2011-06-23 14:01:40

+0

@Tomalak我同意,有时知道你的编译器输出是必要的。但对大多数情况来说,这并不重要。 – 2011-06-23 14:03:36

+2

当然。另一方面,了解您的工具以及如何正确使用它们。 – 2011-06-23 14:06:32

2

说到MS,它是链接器,它在链接阶段处理此问题,并且编译器可能会警告您未使用的静态函数(文件范围)。如果您希望链接器删除未使用的函数,请使用/OPT:REF选项:

4

使用gcc如果启用优化,它可以删除未使用的函数和死代码。

更多关于GCC的优化,可以发现here

5

许多编译器做的,但是这取决于具体的实施。调试版本通常会包含所有功能,以便在调试器中调用或检查它们。由于我不完全了解(*)的原因,许多嵌入式系统编译器将包含对象文件中的所有功能(如果它们包含任何功能),但会完全省略完全不使用的任何对象文件。

请注意,在支持Reflection的语言(例如Java,C#,vb.net等)中,给定一个函数的名字,可以在运行时创建对它的引用,即使代码中没有引用。例如,一个例程可以接受来自控制台的字符串,以某种方式使用该字符串,并以该名称生成对函数的调用。编译器或链接器无法知道可能会如此生成哪些名称,因此无法知道可以安全地从代码中省略哪些函数。但是,在C或C++中不存在这样的困难,因为没有定义的方法让代码创建对函数,变量或常量的引用,而不在代码中存在明确的引用。有些实现可能会安排一些事情,以便连续声明的常量或变量将被连续存储,因此可以通过向先前声明的一个偏移量添加偏移量来创建对后面声明的引用的引用,但这些技巧的行为是明确的不受C或C++标准的保证。 (*)我知道它使得编译和链接变得更加容易,但是今天的计算机应该没有运行更复杂的编译和链接算法的麻烦,而这种算法比过去几十年来的实践要容易。如果没有别的,预编译/链接阶段可以使用两步预编译/预链接/编译/链接方法生成所使用的事物列表,然后在“真实”编译/链接阶段省略那些不是。

+0

虽然我猜想一些令人头疼的内联程序集可能会调用一个本来可以安全使用的函数从代码中省略? – Andy 2017-07-06 23:27:07

+0

@Andy;一般来说,只有当它使用有关函数的地址时。 – supercat 2017-07-07 05:43:28

15

如果使用/Gy进行编译并链接到/OPT:REF,MSVC(Visual Studio编译器/链接器)可以执行此操作。

如果您使用-ffunction-sections -fdata-sections进行编译并链接到--gc-sections,GCC/binutils可以执行此操作。

不知道其他编译器。

+0

请注意,'/ OPT:REF'会导致非标准行为:它将优化仅取得地址的函数,以使地址变为无效。 GCC不会发生这种情况。 – rubenvb 2016-08-10 05:29:38

12

一般来说,答案是:

是:未使用static功能。

编号:  未使用的全局可用函数。

编译器不知道其他编译单元是否引用它。而且,大多数对象模块类型不允许在编译后删除函数,也不提供链接器判断是否存在内部引用的方法。 (链接器可以分辨出是否有外部。)有些链接器可以做到这一点,但很多事情都可以解决这个问题。

当然,它自己的模块中的函数不会被任何链接器不必要地加载,除非它是共享库的一部分。 (因为它在将来可能会在运行时被引用,很明显。)