g++ 对于看似不相关的变量“警告:迭代...调用未定义的行为”

2024-05-20

考虑以下代码strange.cpp:

#include <vector> 


using namespace std;


int i = 0;


int *bar()
{   
    ++i;
    return &i; 
}   


int main()
{   
    for(size_t j = 0; j < 99999999999; ++j) // (*)
    {   
        const auto p = bar();
        if(!p) // (**)
            return -1; 
    }   
}   

用 g++ 编译它会发出警告:

$ g++ --std=c++11 -O3 strange.cpp 
strange.cpp: In function ‘int main()’:
strange.cpp:12:12: warning: iteration 4294967296ul invokes undefined behavior [-Waggressive-loop-optimizations]
         ++i;
            ^
strange.cpp:19:9: note: containing loop
         for(size_t j = 0; j < 99999999999; ++j) // (*)
         ^

我不明白为什么增量会调用未定义的行为。此外,还有两个更改,每个更改都会使警告消失:

  1. 改变线路(*) to for(int j...
  2. 改变线路(**) to if(!*p)

此警告的含义是什么?为什么要进行相关更改?

Note

$ g++ --version
g++ (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4

The increment is undefined because once i reaches std::numeric_limits<int>::max() http://en.cppreference.com/w/cpp/types/numeric_limits/max (231 - 1 on a 32-bit, LP64 or LLP64 platform), incrementing it will overflow, which is undefined behavior for signed integral types.

gcc is warning on iteration 4294967296ul (232) rather than iteration 2147483646u (231) as you might expect, because it doesn't know the initial value of i; some other code might have run before main to set i to something other than 0. But once main is entered, no other code can run to alter i, and so once 232 iterations have completed it will have at some point reached 231 - 1 and overflowed.

  1. 通过将循环的控制条件转变为同义反复的真实表达式来“修复”它;这使得循环成为无限循环,因为if循环内部永远不会执行,因为&i不能是空指针。无限循环可以被优化掉 https://stackoverflow.com/questions/2178115/are-compilers-allowed-to-eliminate-infinite-loops,因此 gcc 消除了循环体和整数溢出i不会发生。

  2. 通过允许 gcc 摆脱整数溢出的未定义行为来“修复”它。防止整数溢出的唯一方法是i具有负的初始值,这样在某个时刻i达到零。这是可能的(见上文),唯一的选择是未定义的行为,所以它must发生。所以i达到零时,if循环内部执行,并且main回报-1.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

g++ 对于看似不相关的变量“警告:迭代...调用未定义的行为” 的相关文章

随机推荐