当使用优化标志计算简单的有限差分时,clang ++ v6,7&8 bug /错误结果

Pic*_*ent 5 c++ clang++

我的一位同事发现了这个有趣/令人惊讶的错误.

当使用优化标志(通常为-O2)进行编译时,它会影响clang ++版本6,7和8

代码非常简单,它必须计算有限的差异:

a[i] = x[i+1]-x[i]
b[i] = (y[i+1]-y[i])/a[i]
Run Code Online (Sandbox Code Playgroud)

副代码演示如下:

#include <iostream>
#include <vector>

class Foo {
private:
    std::vector<double> _a;
    std::vector<double> _d;

public:
    Foo(const std::vector<double> &x, const std::vector<double> &y)
        : _a(x.size()), _d(x.size()) {

        for (unsigned int i = 0; i < x.size() - 1; i++) {
            _a[i] = x[i + 1] - x[i];
            _d[i] = (y[i + 1] - y[i]) / _a[i];
        }
    }

    const std::vector<double> &a() const noexcept { return _a; }
};

int main() {

    // Read input file
    std::vector<double> x, y;
    while (std::cin) {
        double xi, yi;
        if (std::cin >> xi >> yi) {
            x.push_back(xi);
            y.push_back(yi);
        }
    }

    // Create Foo instance
    Foo foo(x, y);

    // Print computed data
    for (auto a : foo.a()) std::cout << a << '\n';

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当您使用未经优化的clang编译时:

$> clang++-6.0 -std=c++11 -o bug  bug.cpp
$> paste <(seq 1 5) <(seq 1 5) | ./bug
Run Code Online (Sandbox Code Playgroud)

你得到了预期的结果:

1
1
1
1
0
Run Code Online (Sandbox Code Playgroud)

但是在优化时(-O2选项):

$> clang++-6.0 -std=c++11 -O2 -o bug  bug.cpp
$> paste <(seq 1 5) <(seq 1 5) | ./bug
Run Code Online (Sandbox Code Playgroud)

你得到一个错误的结果:

1
2
2
0
0
Run Code Online (Sandbox Code Playgroud)
  • 你可以重现吗?
  • 它固定了吗?

Pic*_*ent 6

该错误已经确认(具有"释放阻止程序"优先级),现在已经修复了2天:详情请见此处

请注意:

  • valgrind什么都没报告< - >难以隔离这个bug
  • g ++不受影响

我认为这个错误值得一提,因为它可能会严重,但却默默地影响数值计算代码.