澄清什么是heisenbug

del*_*bao 10 terminology

我阅读了关于heisenbug的维基页面,但是不明白这个例子.任何人都可以详细解释一下吗?

heisenbug的一个常见示例是在使用优化编译器编译程序时出现的错误,但是在没有优化的情况下编译相同程序时则不会出现错误(通常是为了使用调试器进行检查).在调试时,优化程序通常保留在寄存器中的值通常会被推送到主存储器.例如,这可能会影响浮点比较的结果,因为存储器中的值可能比寄存器中的值具有更小的范围和精度.

Per*_*xty 10

这是最近发布的具体示例:

无限循环heisenbug:如果我添加打印输出它会退出

这是一个非常好的标本,因为我们都可以重现它:http://ideone.com/rjY5kQ

这些错误非常依赖于平台的非常精确的功能,人们也发现它们很难再现.


在这种情况下,当省略'打印输出'时,程序在CPU寄存器内执行高精度比较(高于存储在a中double).但是要打印出值,编译器决定将结果移动到主存储器,这会导致精度的隐式截断.当它使用截断值进行比较时,它会成功.

#include <iostream>
#include <cmath>

double up = 19.0 + (61.0/125.0);
double down = -32.0 - (2.0/3.0);
double rectangle = (up - down) * 8.0;

double f(double x) {
    return (pow(x, 4.0)/500.0) - (pow(x, 2.0)/200.0) - 0.012;
}

double g(double x) {
    return -(pow(x, 3.0)/30.0) + (x/20.0) + (1.0/6.0);
}

double area_upper(double x, double step) {
    return (((up - f(x)) + (up - f(x + step))) * step) / 2.0;
}

double area_lower(double x, double step) {
    return (((g(x) - down) + (g(x + step) - down)) * step) / 2.0;
}

double area(double x, double step) {
    return area_upper(x, step) + area_lower(x, step);
}

int main() {
    double current = 0, last = 0, step = 1.0;

    do {
        last = current;
        step /= 10.0;
        current = 0;

        for(double x = 2.0; x < 10.0; x += step) current += area(x, step);

        current = rectangle - current;
        current = round(current * 1000.0) / 1000.0;
        //std::cout << current << std::endl; //<-- COMMENT BACK IN TO "FIX" BUG
    } while(current != last);

    std::cout << current << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编辑:已验证的错误和修复仍然展示:20-Feb-17


sas*_*tch 6

它来自不确定性原理,该原理基本上指出,对精度的基本限制是可以同时知道粒子的某些成对物理特性的。如果您开始太近地观察某些粒子(即,您确切地知道它的位置),那么您将无法精确地测量其动量。(如果您具有精确的速度,则无法确定其确切位置)

因此,在此之后,Heisenbug是一个错误,当您仔细观察时,该错误会消失。

在您的示例中,如果您需要程序执行良好,则将对其进行优化编译,并且会出现错误。但是,一旦进入调试模式,您就不会通过优化对其进行编译,这会消除该错误。

因此,如果您过分仔细地观察该错误,您将不确定是否知道该属性(或找不到它),该属性类似于海森堡的不确定性原理,因此被称为海森贝格。