g++ “warning: iteration … invokes undefined behavior” for Seemingly Unrelated Variable

旧巷老猫 提交于 2019-12-10 16:29:58

问题


Consider the following code in 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; 
    }   
}   

Compiling this with g++ gives a warning:

$ 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) // (*)
         ^

I don't understand why the increment invokes undefined behavior. Moreover, there are two changes, each of which makes the warning disappear:

  1. changing the line (*) to for(int j...
  2. changing the line (**) to if(!*p)

What is the meaning of this warning, and why are the changes relevant to it?

Note

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

回答1:


The increment is undefined because once i reaches std::numeric_limits<int>::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. "fixes" it by turning the controlling condition of the loop into a tautologically true expression; this makes the loop an infinite loop, since the if inside the loop will never execute, as &i cannot be a null pointer. Infinite loops can be optimized away, so gcc eliminates the body of the loop and the integer overflow of i does not occur.

  2. "fixes" it by allowing gcc an out from the undefined behavior of integer overflow. The only way to prevent integer overflow is for i to have an initial value that is negative, such that at some point i reaches zero. This is possible (see above), and the only alternative is undefined behavior, so it must happen. So i reaches zero, the if inside the loop executes, and main returns -1.



来源:https://stackoverflow.com/questions/35299041/g-warning-iteration-invokes-undefined-behavior-for-seemingly-unrelated

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!