闲置代码中的开销

问题描述

我想知道在您的代码中使用未使用的功能会带来多少开销。 假设您有一些调试日志记录,然后为大多数对象提供了调试日志中正在使用的ToString()函数。 在发行版中,没有使用调试日志记录。那么值得删除那些ToString()函数的源代码吗? (例如通过Macro?) 还是它们只是使可执行文件略大,否则不会影响性能?例如没有速度影响?还是如果不使用这些功能,编译器或链接器甚至可能会删除这些功能?如果编译器或链接器没有删除代码,那么如果ToString()函数是内联定义的,该怎么办?大概它将尝试内联代码,并且由于从未调用过该函数,它将消失吗? 我想每个功能都需要保留在静态库中,但是一旦编译为可执行文件链接器会忽略很多东西吗? 在另一个大致相似的注释上,如果编译器选择不内联一个内联函数,以便将内联函数定义为多个编译单元中的函数,则链接器将舍弃多余的定义,仅在最后链接其中一个? 谢谢     

解决方法

它取决于编译器,我想取决于优化级别。 G ++和MSVC ++删除了未使用的内联函数,但保留了未使用的非内联函数。 例如,您在正常程序中仅使用STL的一小部分。所有未使用的功能都将被删除,因为它们被定义为内联。 另一方面,GCC保留所有功能,即使未使用的内联功能也是如此。 回答另一个问题:如果在多个编译单元中以某种方式定义了函数,则链接器将皱眉并拒绝链接,除非将其定义为内联。     ,1.关于编译器和链接器 这实际上取决于您如何创建可执行文件。 通常,可执行文件会被删除任何未使用的东西。因此,如果您静态链接(并使用正确的优化选项),这些功能将被删除。 但是,如果您动态链接,它们将在那里,因为就库而言,它们将被导出并因此被使用。 至于多个定义,取决于符号是否弱。如果它很弱,则链接器将选择其中一个定义,否则将对其阻塞。 最后,它们可能仅代表程序的边缘部分。 2.如何解决问题? 这是一个很难的问题,您始终可以使用预处理器删除某些内容,但是用预处理器指令乱七八糟的代码确实令人讨厌阅读。 就个人而言,我不会打扰……尤其是因为我也登录了Release(否则如何跟踪生产问题?)。 一个解决方案可能是在一个单独的文件中定义有问题的功能,而不在Release中链接它们。注意:我认为它不适用于虚拟函数,因为它们至少在vtable中使用了     ,链接器会删除重复的功能,并且会删除未引用的数据(Microsoft链接器提供了“ 0”和“ 1”开关来调整这些设置)。 您肯定是对的,在大多数情况下,链接器是否可以很好地删除不需要的或多余的内容就不重要了-一些小功能对可执行文件大小的影响(与纯粹的数量相比)如果您广泛使用STL或其他模板库,则生成的代码数量很少。 就是说,如果您需要使可执行文件尽可能小(或者发现调试代码确实占用了大部分映像大小),则将所有内容“ 2”化是强制执行某些不包含的功能的最简单方法。它使代码阅读起来有些丑陋,但是它的优点是您不会偶然错过发行版本中的调试代码,因为任何试图调用不存在的函数的尝试都会导致编译器错误。
#ifdef
的另一个优点是它是可移植的,并且不依赖于特定的编译器系统:-/     ,如果您将非虚拟函数放在库中的单独文件中,并且 静态链接,仅当它是可执行文件时,才应将其添加到可执行文件中 用过的。但是,唯一真正的区别在于 可执行文件可以想象这可能会影响本地性,因此 性能,但如果能真正发挥作用,我会感到非常惊讶 在实践中。所以总的来说,我会说这种技术不值得 麻烦一个应用程序。 (如果您要提供第三方库, 另一方面,您绝对希望每个非虚拟功能都包含在 单独的文件。)