-O2 优化不会在读取大文件时出圈

-O2 optimization does not go out of the loop if reading large file

本文关键字:文件 读取 优化 -O2      更新时间:2023-10-16

我对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实例(EC2 c3.2xlarge和Ubuntu 16.42(中测试了代码,它显示了类似的行为。(我正在为 Windows 10 使用 bash(。

我不知道这段代码中到底发生了什么。如果有一个解决方案可以在不丢弃-O2-O3选项的情况下运行类似的代码,那就太好了!谢谢。

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

例如,允许优化器假定i永远不会大于(2^31 - 1) / 60000,因为它可以假设 UB 永远不会发生,并且根据该逻辑,循环条件始终为真。(可能是也可能不是确切发生的事情,UB可以通过各种方式破坏事物。

请改用int64_t i