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

9
我正在寻找触发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

我正在寻找没有宏的代码示例,这些示例在多次运行编译器时会导致不同的输出,但可以通过例如-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. 

7
@tadman说,StackOverflow也涉及开发者使用的工具,因此这确实是符合要求的。请重新阅读https://stackoverflow.com/help/on-topic。 - rubenvb
3
@tadman,说实话我并不在乎这个问题被关闭的投票数。这是一个非常可回答的问题(哪些代码/选项触发了这种行为),涉及到开发人员通常使用的工具(编译器)。我无法回答它。看起来你也不能,但这并不意味着这个问题与主题无关。 - rubenvb
1
@sdgfsdh 这只是皮毛。要正确回答这个问题需要大量的努力和对话。这是一个好问题,但它太广泛了,在这里无法回答。论坛允许更多的来回交流和澄清。Stack Overflow 不应该以这种方式工作。 - tadman
2
据我所知,根据@rubenvb上面的链接所描述的规则,这个问题是符合主题的。具体来说,它是“关于程序员常用的软件工具”,并且是“一个实际的、可回答的问题,与软件开发独特相关”。 - Jeremy Friesner
我认为你的问题非常宽泛。我建议你在这里看一下:https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options,那里有一些代码示例。也许在你查看了那里并从那里关联的链接中获取了更多信息后,你可以回来提出一个更具限制性的问题。 - Dr t
显示剩余7条评论
1个回答

4

虽然这个问题比较陈旧,但它对于可重复生成的构建(reproducible builds)是有意思的。

正如你所说,在编译某些 C/C++ 源码时会存在多个非确定性来源。

预处理器中的非确定性

预处理器通常实现了一些众所周知的“超级”宏,这些宏在不同运行之间会发生变化。其中有明显的 __DATE____TIME__,还有一些不太明显的,如 __cplusplus__STD_C_VERSION__ 或者 __GNUC_PATCHLEVEL__,这些宏可能会随着操作系统的更新而发生变化。

此外,__FILE__ 也会包含编译环境的路径(因机器而异)。

请注意,在前面提到的宏中,GCC 会观察环境变量 SOURCE_DATE_EPOCH 并重写日期和时间宏。其他编译器可能有其他行为。

编译器中的非确定性

编译器可能基于非确定性方法采用不同的优化策略。你已经在 GCC 中引用了一个例子,但其他编译器可能也存在类似情况。例如,对于 MSVC,你可能会感兴趣的是编译器标志 /BREPRO

你需要阅读你所使用编译器的文档以了解更多信息。

链接器中的非确定性

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

此外,如果你使用链接时优化(Link Time Optimization),许多编译器将创建随机命名的 .o 文件的不同版本。对于 GCC,你可以使用 -frandom-seed=31415 来“固定”这种随机性,但效果因人而异。

构建过程中的非确定性

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

要了解关于确定性构建的详细概述,请参考这篇文章


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接