C++ 不同大小的gcc编译二进制文件?

C++ 不同大小的gcc编译二进制文件?,c++,linux,gcc,elf,C++,Linux,Gcc,Elf,如果使用gcc在不同的时间构建相同的代码,则生成的二进制文件将具有不同的内容。好吧,我对此并不疯狂,但事实就是这样 然而,我最近遇到了这样一种情况:使用相同版本的gcc构建的相同代码生成的二进制文件的大小与以前的构建不同(大约1900字节) 有人知道这两种情况的原因吗?这是某种精灵问题吗?是否有任何工具(ldd除外)可用于转储二进制文件的内容,以查看到底有什么不同 提前谢谢 一个可复制的示例将有助于: 您是否使用其他外部库 你是静态链接还是动态链接 您是否更改了-O或-s之类的标志 这有点像,

如果使用gcc在不同的时间构建相同的代码,则生成的二进制文件将具有不同的内容。好吧,我对此并不疯狂,但事实就是这样

然而,我最近遇到了这样一种情况:使用相同版本的gcc构建的相同代码生成的二进制文件的大小与以前的构建不同(大约1900字节)

有人知道这两种情况的原因吗?这是某种精灵问题吗?是否有任何工具(ldd除外)可用于转储二进制文件的内容,以查看到底有什么不同


提前谢谢

一个可复制的示例将有助于:

  • 您是否使用其他外部库
  • 你是静态链接还是动态链接
  • 您是否更改了-O或-s之类的标志

这有点像,答案是编译器的内部状态可能在不同的编译器运行时有所不同,这可能会导致发出不同的代码,从而具有不同的大小

objdump
可能是您正在寻找的用于转储二进制文件内容的程序


objdump-h
将向您显示各节及其大小,因此您应该能够看到大小变化发生的位置,然后进一步深入了解原因。

用于执行此操作的DEC VMS编译器。原因是优化器可以做得更好,因为它必须使用更多的空闲RAM。显然,每次编译时都很难获得完全相同数量的可用RAM


我记得当时有些人对此感到震惊。对于那些喜欢通过区分生成的二进制文件来检查源代码更改的人来说,情况尤其如此。我当时和现在的建议是克服它。来源你可以“区分”。对于二进制文件,唯一的保证是从同一源文件编译的两个可执行文件都将执行您告诉它们的操作。

除了需要检查所链接的标准库的编译器之外。检查它们的版本并验证它们是否没有更改。

在其他相同版本之间存在大小差异的一个可能原因是二进制文件中可能存储了大小可变的信息。一些例子:

  • 编译器可能正在放置有关编译中涉及的文件的路径/名称信息,用于调试信息或由于使用了
    \uuuuu FILE\uuuu
    宏。它可能是为了自己的目的而这样做的,而这与这些事情都无关。如果构建发生在目录结构稍有不同的不同机器上,这可以解释二进制文件的差异
  • 同样,对于构建的日期/时间,虽然我希望它们很少进入二进制文件(但我知道什么?)。如果这是一个促成因素,您会看到在同一台机器上,即使是相同的构建,在不同的Enough时间,也会有不同的大小

这些事情可以归结为构建机器状态的差异。

我已经设法解决了问题,至少让我满意,并希望传递我的发现

使用readelf,(readelf-a-W)我创建了一个报告,列出了两个版本的内容,并对它们进行了比较(使用Beyond Compare)。这表明有几个额外的符号从boostlibs中被引入

你瞧,事实上,我们是在构建一个不同版本的依赖库,却没有意识到这一点。在这种情况下不会造成任何伤害,但最好知道可执行文件中的内容


感谢大家周到的回复。

编译器标志也是我想到的第一件事。特别是像-O这样的东西。在亲密的猴子们对此感到高兴之前,我应该指出,问题是在不同的(Windows风格的)平台上编译时获得不同的exe。这个问题是关于使用完全相同的编译器在完全相同的平台上获得不同的exe…也就是说,你给出的答案确实很好。好吧,平台应该是相同的。(所有内容都是通过专用构建服务器构建的)。所以,我们试图找出的是哪里出了问题。请阅读这两篇文章-可能没有什么出了问题。可以想象,编译器在同一台机器上运行时处于不同的状态,这取决于其他情况。我个人的期望是编译器的行为是确定性的,至少就产生的输出而言,我认为非常重要的是,当你给编译器相同的源代码和相同的构建设置时,它总是以字节对字节的方式输出完全相同的可执行文件。否则,如果优化器中有一个bug,您可能会得到一些构建“正常”而另一些“不正常”,这完全取决于构建可执行文件时碰巧空闲的RAM数量。。。。调试真是一场噩梦!即使编译器没有bug,您的一些构建也会比其他构建运行得更快,尽管源代码在所有情况下都是相同的。您可能想要这样做,但正如TED和我所指出的,您不能拥有它。您是否愿意提供一个参考,说明gcc有这种不正常的行为,因为这就是OP的问题所在?