C++ 编译器中有哪些不确定性的例子?

Gae*_*ano 5 c++ gcc deterministic clang

我正在寻找在 GCC 或 Clang 的编译过程中触发非确定性的代码示例。

一个突出的例子是__DATE__宏的使用。

GCC 和 Clang 有大量编译器标志来控制编译器中非确定性操作的结果,例如。-frandom-seed-fno-guess-branch-probability

有没有受这些标志影响的小例子?

更准确地说:

$ c++ main.cpp -o main && shasum main
aabbccddee

$ c++ main.cpp -o main && shasum main
eeddccbbaa
Run Code Online (Sandbox Code Playgroud)

我正在寻找无宏代码示例,其中多次运行编译器会导致不同的输出,但可以通过例如修复-frandom-seed

编辑:

相关:来自gcc文档:

-fno-guess-branch-probability:
Sometimes gcc will opt to use a randomized model to guess branch probabilities, 
when none are available from either profiling feedback (-fprofile-arcs) 
or __builtin_expect. 
This means that different runs of the compiler on the same program
may produce different object code.
The default is -fguess-branch-probability at levels -O, -O2, -O3, -Os. 
Run Code Online (Sandbox Code Playgroud)

xry*_*669 4

虽然这个问题很老,但对于可重现的构建来说很有趣。

正如您所说,在编译某些 C/C++ 源代码时,存在多种不确定性来源。

预处理器中的非确定性

预处理器通常会实现一些在运行之间变化的超级宏。当操作系统更新时,有明显的和不明显的或可能会发生变化__DATE____TIME__情况__cplusplus__STD_C_VERSION____GNUC_PATCHLEVEL__

还有__FILE__包含构建环境的路径(因机器而异)。

请注意,对于前一个宏,GCC 会观察环境变量SOURCE_DATE_EPOCH来覆盖日期和时间宏。其他编译器可能有一些其他行为。

编译器中的非确定性

编译器可能有基于非确定性方法的不同优化策略。您在 GCC 中引用了一个,但其他可能也存在。对于 MSVC,您可能对编译器标志感兴趣/BREPRO

您必须通过 RTFM 来让您的编译器了解更多信息。

链接器中的非确定性

在某些体系结构上,链接的对象和/或库将包含时间戳。MacOS 就是其中之一。因此,对于同一组 .o 文件,您将得到不同的可执行文件。

另外,如果您使用链接时间优化,许多编译器将创建随机命名的不同版本的 .o 文件。同样,对于 GCC,您将使用-frandom-seed=31415“修复”这种随机性,但是 YMMV。

构建过程中的非确定性

有时存储库包含在编译阶段之外执行的附加操作。就像根据某些配置标志(或其他步骤)生成头文件一样。在这种情况下,每个项目的具体操作也可能不是确定性的。

有关确定性构建的详细概述,请参阅这篇文章