一个相当简单的问题......这些天的编译器倾向于进行大量的优化。它们是否也从最终输出中删除未使用的函数?
答案 0 :(得分:26)
这取决于编译器。 Visual C ++ 9可以做到这一点 - 在编译阶段删除了未使用的static
函数(甚至还有C4505 warning),可以在链接阶段depending on linker settings删除带有外部链接的未使用函数。 / p>
答案 1 :(得分:21)
如果使用/Gy
进行编译并与/OPT:REF
链接,则MSVC(Visual Studio编译器/链接器)可以执行此操作。
如果您使用-ffunction-sections -fdata-sections
进行编译并与--gc-sections
相关联,则GCC / binutils可以执行此操作。
不了解其他编译器。
答案 2 :(得分:16)
作为一般规则,答案是:
对于未使用的static
函数,是。
否:表示未使用的全局可用功能。
编译器不知道某个其他编译单元是否引用它。此外,大多数对象模块类型不允许在编译后删除函数,也不提供链接器告知是否存在内部引用的方法。 (链接器可以判断是否有外部。)一些链接器可以做到这一点,但很多事情都可以解决这个问题。
当然,任何链接器都不会不必要地加载其自己模块中的函数,除非它是共享库的一部分。 (因为它可能在将来在运行时被引用,显然。)
答案 3 :(得分:5)
使用gcc如果打开optmizations,它可以删除未使用的函数和死代码。
有关gcc优化的更多信息,请访问here
答案 4 :(得分:5)
许多编译器都这样做,但这取决于具体的实现。调试版本通常包含所有函数,以允许在调试器中调用或检查它们。由于我不完全理解(*)的原因,许多嵌入式系统编译器将包含目标文件中的所有函数(如果它们包含任何函数),但将完全省略任何未使用的目标文件。
请注意,在支持Reflection的语言(例如Java,C#,vb.net等)中,在给定函数名称的情况下,即使代码中不存在引用,也可以在运行时创建对它的引用。例如,例程可以接受来自控制台的字符串,以某种方式对其进行处理,并通过该名称生成对函数的调用。编译器或链接器无法知道可能生成的名称,因此无法知道代码中可以安全地省略哪些函数。但是,在C或C ++中不存在这样的困难,因为代码没有定义的方法来创建对函数,变量或常量的引用,而代码中不存在显式引用。一些实现可以安排事情,以便连续存储连续声明的常量或变量,并且可以因此通过向先前声明的一个添加偏移来创建对稍后声明的常量的引用,但是这样的技巧的行为是明确的不受C或C ++标准保证。
(*)据我所知,它使编译和链接变得更容易,但今天的计算机应该可以毫不费力地运行比过去几十年实际更复杂的编译和链接算法。如果没有别的,两个预编译/预链接/编译/链接方法可以在预编译/链接阶段产生一个使用的东西列表,然后在“真正的”编译/链接阶段省略那些不是。
答案 5 :(得分:3)
很多时候,是的。它通常被称为链接器剥离。
答案 6 :(得分:2)
当谈到MS时,链接器会在链接阶段处理这个问题,编译器可能会警告您未使用的静态函数(文件范围)。如果希望链接器删除未使用的函数,请使用/OPT:REF选项:
答案 7 :(得分:1)
在MSVC下,使用全局函数或变量,您可以使用__declspec( selectany )。
如果选择了链接器选项/ OPT:REF(Optimizations),它将删除代码中未引用的函数或变量。
答案 8 :(得分:-3)
这完全取决于编译器及其设置(“调试”配置中内置的代码通常未优化),以及代码本身和行星对齐。
根本的事情是:你不应该担心那些东西。相信你的编译器。