几天前,我遇到了一些我认为是g++ 5.3中关于嵌套for循环在更高的-OX
优化级别下的错误。(具体表现在-O2
和-O3
上)。问题是如果你有两个嵌套的for循环,其中有一些内部总和来跟踪总迭代次数,一旦这个总和超过其最大值,它会防止外层循环终止。我能复制出最小的代码集是:
int main(){
int sum = 0;
// Value of 100 million. (2047483648 less than int32 max.)
int maxInner = 100000000;
int maxOuter = 30;
// 100million * 30 = 3 billion. (Larger than int32 max)
for(int i = 0; i < maxOuter; ++i)
{
for(int j = 0; j < maxInner; ++j)
{
++sum;
}
std::cout<<"i = "<<i<<" sum = "<<sum<<std::endl;
}
}
使用
g++ -o run.me main.cpp
进行编译后,输出与预期一致:i = 0 sum = 100000000
i = 1 sum = 200000000
i = 2 sum = 300000000
i = 3 sum = 400000000
i = 4 sum = 500000000
i = 5 sum = 600000000
i = 6 sum = 700000000
i = 7 sum = 800000000
i = 8 sum = 900000000
i = 9 sum = 1000000000
i = 10 sum = 1100000000
i = 11 sum = 1200000000
i = 12 sum = 1300000000
i = 13 sum = 1400000000
i = 14 sum = 1500000000
i = 15 sum = 1600000000
i = 16 sum = 1700000000
i = 17 sum = 1800000000
i = 18 sum = 1900000000
i = 19 sum = 2000000000
i = 20 sum = 2100000000
i = 21 sum = -2094967296
i = 22 sum = -1994967296
i = 23 sum = -1894967296
i = 24 sum = -1794967296
i = 25 sum = -1694967296
i = 26 sum = -1594967296
i = 27 sum = -1494967296
i = 28 sum = -1394967296
i = 29 sum = -1294967296
然而,当使用
g++ -O2 -o run.me main.cpp
编译时,外部循环无法终止。(只有当 maxInner * maxOuter > 2^31
时才会出现这种情况)尽管 sum 不断溢出,但它不应以任何方式影响其他变量。我还在 Ideone.com 上使用了这个测试示例进行了测试:https://ideone.com/5MI5Jb
我的问题有两个:
- 如何可能使 sum 值以某种方式影响系统? 没有根据其值做出任何决策,它仅仅被用作一个计数器和
std::cout
语句。 - 什么可能导致在不同优化级别下产生截然不同的结果?
i
和 j
都不超过100m,更不用说 2^31 了。