日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【转】C 编译器优化过程中的 Bug

發布時間:2025/6/15 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】C 编译器优化过程中的 Bug 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

C 編譯器優化過程中的 Bug

一個朋友向我指出一個最近他們發現的 GCC 編譯器優化過程(加上 -O3 選項)里的 bug,導致他們的產品出現非常詭異的行為。這使我想起以前見過的一個 GCC bug。當時很多人死活認為那種做法是正確的,跟他們說不清楚。簡言之,這種有問題的優化,喜歡利用 C 語言的“未定義行為”(undefined behavior)進行推斷,最后得到奇怪的結果。

這類優化過程的推理方式都很類似,他們使用一種看似嚴密而巧妙的推理,例如:“現在有一個整數 x,我們不知道它是多少。但 x 出現在一個條件語句里面,如果 x > 1,那么程序會進入未定義行為,所以我們可以斷定 x 的值必然小于或者等于 1,所以現在我們利用 x ≤ 1 這個事實來對相關代碼進行優化……”

看似合理,然而它卻是不正確的,你能看出來這樣的推理錯在何處嗎?我一時想不起來之前具體的例子了(如果你知道的話告訴我)。上網搜了一下相關話題,發現這篇 Chris Lattner (LLVM 和 Swift 語言 的設計者)?寫于 2011 年的文章。文中指出,編譯器利用 C 語言的“未定義行為”進行優化,是合理的,對于性能是很重要的,并且舉出這樣一個例子:

void contains_null_check(int *P) { int dead = *P; if (P == 0) return; *P = 4; }

這例子跟我之前看到的 GCC bug 不大一樣,但大致是類似的推理方式:這個函數依次經過這樣兩個優化步驟(RNCE 和 DCE),之后得出“等價”的代碼:

void contains_null_check_after_RNCE(int *P) { int dead = *P; if (false) // P 在上一行被訪問,所以這里 P 不可能是 null return; *P = 4; } void contains_null_check_after_RNCE_and_DCE(int *P) { //int dead = *P; // 死代碼消除 //if (false) // 死代碼 // return; // 死代碼 *P = 4; }

他的推理方式是這樣:

  • 首先,因為在 int dead = *P 里面,指針 P 的地址被訪問,如果程序順利通過了這一行而沒有出現未定義行為(比如當掉),那么之后 P 就不可能是 null,所以我們可以把 P == 0 優化為 false。
  • 因為條件是 false,所以整個 if 語句都是死代碼,被刪掉。
  • dead 變量賦值之后,沒有被任何其它代碼使用,所以對 dead 的賦值是死代碼,可以消去。
  • 最后函數就只剩下一行代碼 *P = 4。然而經我分析,發現這個優化轉換是根本錯誤的做法(unsound 的變換),而不只是像他說的“存在安全隱患”。現在我來考考你,你知道這為什么是錯的嗎?值得慶幸的是,現在如果你把這代碼輸入到 Clang,就算加上 -O3 選項,它也不會給你進行這個優化。這也許說明 Lattner 的這個想法后來已經被 LLVM 團隊拋棄。

    我寫這篇文章的目的其實是想告訴你,不要盲目的相信編譯器的作者們做出的變換都是正確的,無論它看起來多么的合理,只要打開優化之后你的程序出現奇葩的行為,你就不能排除編譯器進行了錯誤優化的可能性。Lattner 指出這樣的優化完全符合 C 語言的標準,這說明就算你符合國際標準,也有可能其實是錯的。有時候,你是得相信自己的直覺……

    轉載于:https://www.cnblogs.com/alantu2018/p/8547506.html

    總結

    以上是生活随笔為你收集整理的【转】C 编译器优化过程中的 Bug的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。