非决定论的来源

时间:2010-08-31 13:29:26

标签: c++ random deterministic non-deterministic heisenbug

我所谓的确定性程序会在不同的运行中产生一些略有不同的输出。输入,编译器和计算机是不变的。我不确定哪个输出是正确的,因为它看起来总是合理的。

除了对rand()的迷路调用之外,怎么可能这样呢?

12 个答案:

答案 0 :(得分:17)

以多种方式:

  • 以涉及data race
  • 的方式使用多个线程
  • 使用当前系统时间作为输入,
  • 使用未初始化的变量,
  • ...

我们肯定可以做出更多的猜测,但如果你想得到有意义的帮助,也许你可以发布代码的相关部分: - )

答案 1 :(得分:7)

可能是:

  • 线程计时
  • 任何类型的输入(用户,文件,网络等)

答案 2 :(得分:7)

如果输出取决于堆上分配的地址:

int main(int argc, char* argv[])
{
   printf("%p", malloc(42));
   return 0;
}

对于每次运行,malloc()可能会返回一个不同的虚拟地址 - 在分配失败的情况下更不用说NULL。

答案 3 :(得分:5)

  

除了对rand()的迷路调用

rand()只要你给它提供相同的初始种子就完全是确定性的。

答案 4 :(得分:3)

没有看到一些代码(HINT HINT),我能想到的最好的就是找一个模式。也许是特定于日期时间的东西。

此外,尝试寻找竞争条件。这可能看起来不确定。

答案 5 :(得分:3)

如果你的程序使用float / double,如果某些架构上有上下文切换,结果可能会有差异。

在x86上,FPU使用扩展精度作为中间结果,但是当保存在内存中时(在上下文切换进程或线程时发生),这种精度会丢失。这可能会导致结果出现一些小的差异(我们在程序中发现了这样的问题)。避免此问题的一种方法是要求编译器不要使用FPU而是使用SSE进行浮点运算。

http://www.network-theory.co.uk/docs/gccintro/gccintro_70.html

答案 6 :(得分:2)

使用指针的值而不是指向的值总是会产生有趣的结果。

答案 7 :(得分:1)

在与“外部世界”没有太多互动的程序中,非决定论的流行来源是对指针比较的依赖。有时您可能会在代码中看到它:当字典比较函数用完要比较的事物(一切都相同)时,它会将对象的地址作为最后的手段进行比较。如果在动态内存中分配对象,则会产生不同的排序,因为实际的分配位置可能因平台和运行而不同。

答案 8 :(得分:0)

显然是Phase of the Moon错误的新实例。

答案 9 :(得分:0)

  • 来自网络/互联网的输入。
  • 日期/时间

答案 10 :(得分:0)

你没有提供很多信息。然而,作为一个以实时编程为生的人,当这些事情发生时我最想找到的罪魁祸首就是:

  • 使用未初始化的内存。
  • 竞争条件。
  • 上述一些模糊的组合。

例如,我曾经遇到过这样一个问题:共享库不像我想的那样“共享”,并试图使用一个进程的句柄来索引一个在第二个进程中尚未初始化的表。取决于事情的启动方式,可能会或可能不会导致第三个流程中的重要数据被破坏。

答案 11 :(得分:0)

任何未定义的行为。即:需要数百页来解释输出的每个可能的变更来源。尝试调试以找到发生更改的地方,或阅读一些C ++规范。