【问题标题】:How can compiling the same source code generate different object files?编译相同的源代码如何生成不同的目标文件?
【发布时间】:2014-06-10 21:51:55
【问题描述】:

经过一长串调试后,我将问题缩小到一个文件。问题是文件在两个不同的目录中编译不同,而其他一切都相同。

我正在使用 CodeSourcery 的 arm gcc 编译器(gcc 版本 4.3.3,Sourcery G++ Lite 2009q1-161)来编译一个简单的文件。我在一个模块中使用它没有问题,然后我将它复制到另一个模块以在那里使用。编译时,目标文件明显不同。编译这两个文件的命令行是相同的(我用linux历史来确定),3个包含文件也是相同的副本(用diff检查)。

我对两个目标文件进行了二进制比较,它们散布着很多单独的字节差异。我做了一个 objdump -D 并比较了它们,有很多不同之处。这是dump1dump2diff。命令行是“ arm-none-eabi-gcc --std=gnu99 -Wall -O3 -g3 -ggdb -Wextra -Wno-unused -c crc.c -o crc.o"。

这怎么可能?我还使用 -S 而不是 -c 进行了编译,并查看了汇编程序的输出,除了目录路径之外,它是相同的。那么目标文件怎么会不一样呢?

我真正的问题是,当我尝试将 dump2 的目标文件链接到我的程序时,我得到未定义的引用错误,因此对象中的某些内容是错误的,而 dump1 的对象没有出现此类错误并且链接正常。

【问题讨论】:

  • 显然有一个标签binary-reproducibility。我在这个编译器上看到了同样的事情。大多数 diff 显示不同的寄存器选择或文件偏移,但它具有相同的基本功能。请参阅:Debian reproducible builds。当然,输出可能不同。是你的问题吗?我认为您的问题是另一回事。
  • 您可以尝试使用-O0 进行编译以查看差异是否仍然存在。
  • 我有一个类似的问题on ARM。完全相同的代码和编译器,在每种情况下生成的程序集略有不同(不同的寄存器选择)。就好像优化受到一些随机内存问题或一些时间问题的影响。
  • 请注意,在这种情况下,差异中的所有内容看起来都来自 .debug_* 部分。我对 DWARF 格式一无所知,但是当我看到没有字节设置最高位并且序列 2e 2e 2f 分散在各处的废话“指令”时,我知道我正在查看 ASCII 路径字符串。我敢打赌,大部分差异只是因为在不同的位置编译。如果您在没有调试信息的情况下进行编译,它是否可以工作?

标签: c linux gcc compiler-construction arm


【解决方案1】:

对于大型软件,有许多实现对指针进行哈希处理。这是导致结果随机化的主要原因之一。通常如果程序逻辑正确,一些内部数据结构的顺序可能会不同,这在大多数情况下是无害的。

另外,不要比较 'objdump -D' 的输出,因为你是从不同的目录编译代码,字符串表、符号表、DWARF 或 eh_frame 应该是不同的。你肯定会得到很多差异线。

唯一有意义的比较是比较“objdump -d”的输出,它只处理文本部分。如果文本部分相同(相似),则可以认为是相同的。

【讨论】:

    【解决方案2】:

    您的文件很可能会选择不同的包含文件。这是最可能的原因。

    检查您的包含路径是否完全相同,包含语句中的路径。它们可能指向不同的目录。 C 和 C++ 有一个功能,当您 #include abcd.h 时,它会尝试从调用文件的目录加载 abcd.h。检查一下。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-01-18
      • 1970-01-01
      • 2013-06-08
      • 2021-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多