GCC 优化忽略循环条件

问题描述

所以我写了这段代码

#include <iostream>

constexpr
int fibonacci (int n) {
    int a = 0;
    int b = 1;

    for(auto i = 0; i < n; i++) {
        b += a;
        a = b - a;
    }
    return b;
}

template<int N,int (T)(int)>
struct array {
    using type = decltype(T(0));

    constexpr array() : arr() {
        for (auto i = 0; i < N; ++i) {
            arr[i] = T(i);
        }
    }
    const type &operator[](int i) const { return arr[i]; }

private:
    type arr[N];
};

int main() {
    constexpr auto x = array<10,fibonacci>();

    for (int i = 0; i < 11; i++) {
        std::cout << i << " " << x[i] << std::endl;
    }
}

如果没有优化,它会按预期工作,打印 11 个值,最后一个随机值。但是一旦我移动到 -O2,我就会随机得到一长串以崩溃和分段错误完成的数字。 我在godbolt.org (https://godbolt.org/z/4MqjbPbxE) 上查看了这个结果,似乎在例如clang 中没有问题。

我的问题是,这是 gcc 中的错误吗?为什么优化会删除/不检查 for 循环中的条件?

解决方法

您正在使用超出范围的 x[i] 调用未定义的行为

再分配一个以避免超出范围的访问。

换句话说,

    constexpr auto x = array<10,fibonacci>();

应该

    constexpr auto x = array<11,fibonacci>();

定义常量以避免拼写错误更好:

int main() {
    constexpr int num = 11;
    constexpr auto x = array<num,fibonacci>();

    for (int i = 0; i < num; i++) {
        std::cout << i << " " << x[i] << std::endl;
    }
}
,

修复检查索引。

for (int i = 0; i ; i++) {