在不同的机器上编译会产生不同的 Arduino ESP8266 项目的 hex 文件

Compiling on different machines delivers different hex files of Arduino ESP8266 project

我正在使用 Arduino core for ESP8266 开发 ESP8266 应用程序。在不同机器上编译项目后,我注意到两个 *.bin 文件有很大差异。

我用一个空项目重现了这个行为。编译后的结果是:

设备 1:

Program Sketch1 size: 221.999 bytes (used 21% of a 1.044.464 byte maximum) (0,97 secs) Minimum Memory Usage: 31564 bytes (39% of a 81920 byte maximum)

设备 2:

Program Sketch1 size: 221.995 bytes (used 21% of a 1.044.464 byte maximum) (0,63 secs) Minimum Memory Usage: 31568 bytes (39% of a 81920 byte maximum)

用十六进制编辑器比较 *.bin 文件显示出很大差异。 我假设在不同设备上编译相同的应用程序应该生成完全相同的文件。

我无法检测到机器之间的单一差异。有没有一种编译器可以在不同机器上生成不同文件的方法,或者可能是什么问题?

编辑: 我找到了4个字节差异的原因:编译器编译了4次*.bin文件中ESP8266库的路径。由于 windows 用户名不同(1 个字符长度差异),因此加起来为 4 个字节。这解释了不同的文件大小,但没有解释文件内部的差异。

为了向您展示我上传文件的不同之处:

文件显示出多个差异。请注意,这是一个空项目,一个更复杂的项目显示出更多差异。

言归正传:为什么编译后的 *.bin 文件内部存在差异?

我假设代码定义良好,因为对于具有未定义行为的代码,编译器可能会随心所欲地运行。

尽管编译器在不同机器上甚至在同一台机器上的不同调用上生成不同但功能等效的代码并不罕见,但这种情况并不少见。

在编译一个给定的程序时,通常会有许多任意选择,除非编译器程序员特别小心,否则很容易构建一个编译器,它根据执行之间发生变化的事情做出这些选择,例如地址内部数据结构中的元素。更糟糕的是,编译器的这一方面可能不像正确性那样经常被测试。人们通常不关心编译器是不确定的,只要代码是正确的。

这个问题之前已经被问过和回答过。没有理由假设,即使你说的是一个空项目,你每次都会从编译代码中获得相同的二进制文件。人们希望在同一天在同一台机器上使用完全相同的源代码,等等。但是一些编译器会在文件中添加一个 date/time 标记,因此即使在那里你也可能会有一些差异。就机器代码而言,尽管有不止一种方法可以生成与高级语言匹配的功能代码,并且具有不同选项的相同编译器或不同编译器或相同编译器的不同版本甚至相同使用的不同系统库编译器可以产生不同的结果。

一般期望相同的源代码产生相同的二进制文件就是问题所在,期望。您应该期望编译器生成的代码在功能上与您的源代码匹配。

您还在检查 "binary",其中包括调试信息和其他项目,其中只有一部分是重要的机器代码,其余部分用于反汇编或调试或 loading/programming,等等. 除了不必匹配的机器代码之外,额外的东西也不必匹配,共享系统库用于创建二进制文件(unix 方式)的情况并不少见,所以你可以 "exact same" 编译器和源代码,但对同一版本的操作系统进行了不同的更新,如果检查 "binary".

,仍然会得到不同的结果

希望这不再是一种实践,但在 turbo/borland 编译器时代,其中一个编译器会用内存中的任何内容填充结构。所以说你正在研究一些在 ram 中的大程序,你出于某种原因关闭了编辑器,稍后你编译了一个程序,他们需要 256 个字节用于 structure/string 但你只初始化了 200 个,其他 56 个字节将是无论 ram 中剩下什么,他们都不会先将其归零,因此不仅先前运行的随机内容最终会出现在 "binary" 中,每次编译时,即使机器代码和其他一切匹配。再次希望不是今天的做法,通常他们将填充归零,但过去在商业付费编译器中发生过。