我对GCC(G ++)编译器有一个非常奇怪的问题。我的C ++代码如下所示。

int main() {
    ifstream ifsr("some-large-file.bin", ios::binary | ios::in);
    for (int i = 0; i < 50000; i++) {
        ifsr.seekg(60000 * i);
        if (i % 1000 == 0) cout << i << "\n";
    }
    ifsr.close();
    return 0;
}


它应该在i >= 50000之后停止。但是,如果我使用-O2-O3选项编译了代码,则循环不会停止(即使i > 50000,循环也会继续进行)。如果我使用-O选项编译它,它将很好地工作。如果我注释掉ifsr.seekg(60000 * i);行,它也可以很好地工作(即使使用-O2-O3选项)。我还在我的AWS实例(使用Ubuntu 16.42的EC2 c3.2xlarge)中测试了代码,它显示了类似的行为。 (我在Windows 10上使用bash)。

我不知道这段代码真正发生了什么。而且,如果有一种解决方案可以在不删除-O2-O3选项的情况下运行类似的代码,那就太好了!谢谢。

最佳答案

49999*60000 = 2,999,940,000溢出通常的32位带符号int。那是未定义的行为,应该是造成问题的根源。

例如,允许优化器假定i永远不大于(2^31 - 1) / 60000,因为它可以假定UB永远不会发生,并且根据这种逻辑,循环条件始终为true。 (可能不完全是实际发生的情况,UB可以以各种方式破坏事物。)

请改用int64_t i

关于c++ - -O2优化在读取大文件时不会超出循环范围,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42057372/

10-11 10:43