原文: https://mohitmv.github.io/blog/Shocking-Undefined-Behaviour-In-Action/
看到一篇 C++ 未定義行為的簡單例子分享一下
簡單的有限迴圈變成無窮迴圈
1. #include <iostream>
2.
3. int main() {
4. char buf[50] = "y";
5. for (int j = 0; j < 9; ++j) {
6. std::cout << (j * 0x20000001) << std::endl;
7. if (buf[0] == 'x') break;
8. }
9. }
編譯器: GCC 11.1.0
編譯選項: -Wall -Wextra -std=c++17 -pedantic-errors
https://wandbox.org/permlink/h1zB3mYSD3pCHiIV
使用以上編譯選項程式印出 9 次數字後就會正常結束
但是最佳化(-O2 或是 -O3)後執行會變成無窮迴圈
這是因為段程式碼有未定義行為(signed integer overflow)
由於編譯器在最佳化時可以假設 signed integer overflow 不會發生
編譯器會先將程式碼轉換為
1. for (int p = 0; p < 9 * 0x20000001; p += 0x20000001) {
2. std::cout << p << std::endl;
3. if (buf[0] == 'x') break;
4. }
接著把" p < 9 * 0x20000001 " 簡化為 true
因為 4,831,838,217 (9*0x20000001) 比 p 可能的最大值 INT_MAX 還大
所以結果永遠為 true
程式碼因此變成
1. for (int p = 0; true; p+=0x20000001) {
2. std::cout << p << std::endl;
3. if (buf[0] == 'x') break;
4. }
而形成無窮迴圈