有没有理由不从可执行文件中删除符号?

时间:2015-08-25 18:56:37

标签: c++ c compilation mingw

几年前,我问过a question如何减少可执行文件的大小。使用MinGW编译器,剥离符号(-s选项)有助于减少50%+的大小。

为什么剥离不是默认的 - 有什么理由不在某些情况下剥离符号呢?我想更深入地理解它:今天,我只是模糊地知道链接库中涉及符号。它们是否需要可执行文件,它们是否会影响执行速度?

3 个答案:

答案 0 :(得分:8)

我无法想象它们会以任何明显的方式影响执行速度,但理论上,您可能会在过程映像中出现微小的缓存未命中数。

您希望在调试时将符号保留在文件中,以便您可以查看您所在的函数,检查变量的值等等。

但是符号会使文件更大:可能 lot 更大。因此,您不希望将二进制文件中的符号放在小型嵌入式设备上。 (我说的是一个真正的嵌入式设备,而不是21世纪的Raspberry Pi,拥有9,000GB的存储空间!)

我通常会删除所有发布版本,并且不会删除任何调试版本。这使得来自客户的核心转储变得不那么有用,但是您可以随时保留未经剥离的发布版本的副本,并针对该版本调试您的核心。

我确实听说过一家公司,即使在发布版本中也有从不剥离符号的策略,因此他们可以将核心直接加载到调试器中。这看起来像是一个抽象泄漏给我,但无论如何。他们的电话。

当然,如果你真的想要,你可以在没有它们的情况下自己分析装配。但那太疯狂了......

答案 1 :(得分:7)

MinGW是" Windows的极简主义GNU的缩写&#34 ;;因此,编译器套件是GCC ...... GNU编译器集合。当然,这个编译器套件倾向于符合GNU编码标准,该标准要求每个构建都应该是一个"调试版本" ...即它应包括调试符号和链接所需的符号。 (这是合乎逻辑的,因为对于应用程序开发人员而言,#34; debug build"对于所谓的"发布构建"来说是更有用的数量级。此外,一个构建系统区分"调试构建"和"发布版本"模式比只关注"调试版本的模式更复杂 - 可能更为复杂 -

在GNU构建模型中,不需要发布版本"无论如何。 A"发布"不是在构建时创建的;它是在安装时创建的 - 通常是作为"分阶段"安装,从中创建发布。 GNU工具链包括strip命令和install命令,它们可以删除"调试版本"在运行时,当创建一个分阶段安装包装作为一个发布时,(或者如果你愿意的话,到位),所以真的没有必要使构建系统与#34;发布构建"细节;只需创建一个"调试版本"在前面,然后在事件发生后将其删除,以便在需要时将其转换为有效的"发布版本"

由于你的MinGW工具链基本上是一个GNU工具链,它完全支持这个GNU构建模型。

答案 2 :(得分:4)

剥离符号没有充分的理由。例如,通过剥离符号,您将消除收集进程堆栈的可能性 - 这是一个非常有用的功能。

EDIT。这里的几个人似乎对调试符号和“通用”符号之间的区别感到困惑。第一个仅在为编译器提供-g(或类似)选项时生成,并且通常仅在调试版本中使用(尽管也可以与优化版本一起使用)。常规符号是诸如函数名之类的东西,由编译器生成,以便可以链接目标文件,或者加载.so文件。有几种非常有用的非侵入性工具可用于非调试运行的可执行文件,这些可执行文件依赖于非剥离的符号。