[英]Why does this loop produce “warning: iteration 3u invokes undefined behavior” and output more than 4 lines?
[英]g++ “warning: iteration … invokes undefined behavior” for Seemingly Unrelated Variable
請考慮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) // (*)
^
我不明白為什么增量會調用未定義的行為。 此外,有兩個更改,每個更改使警告消失:
(*)
更改for(int j...
(**)
更改為if(!*p)
這個警告的含義是什么,為什么這些變化與之相關?
注意
$ g++ --version
g++ (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
增量是未定義的,因為一旦i
到達std::numeric_limits<int>::max()
(在32位,LP64或LLP64平台上為2 31 - 1),遞增它將溢出,這是有符號整數類型的未定義行為。
gcc在迭代4294967296ul(2 32 )而不是迭代2147483646u(2 31 )上發出警告,因為它不知道i
的初始值 ; 其他一些代碼可能在main
之前運行,將i
設置為0
以外的其他代碼。 但是一旦輸入main
,就沒有其他代碼可以運行來改變i
,因此一旦完成2 32次迭代,它將在某個時刻達到2 31 - 1並溢出。
通過將循環的控制條件轉換為同義的真實表達來“修復”它; 這使得循環成為一個無限循環,因為循環中的if
將永遠不會執行,因為&i
不能是空指針。 無限循環可以被優化掉 ,因此gcc消除了循環體,並且不會發生i
的整數溢出。
通過允許gcc從整數溢出的未定義行為中取出來“修復”它。 防止整數溢出的唯一方法是使i
的初始值為負,這樣在某些時候i
達到零。 這是可能的(見上文),唯一的選擇是未定義的行為,所以它必須發生。 所以i
達到零,循環內的if
執行, main
返回-1
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.