未定義的行為
如果程式包含未定義的行為,則 C++標準不會對其行為施加任何約束。
- 它可能看起來像開發人員的意圖,但它也可能崩潰或產生奇怪的結果。
- 行為可能因同一程式的執行而異。
- 程式的任何部分都可能出現故障,包括在包含未定義行為的行之前的行。
- 不需要實現來記錄未定義行為的結果。
實現可以記錄根據標準產生未定義行為的操作的結果,但是依賴於這種記錄的行為的程式是不可移植的。
為什麼存在未定義的行為
直覺上,未定義的行為被認為是一件壞事,因為這樣的錯誤無法通過異常處理程式來處理。
但是保留一些未定義的行為實際上是 C++承諾的一個組成部分,你不為你不使用的東西買單。未定義的行為允許編譯器假設開發人員知道他在做什麼,而不是引入程式碼來檢查上面示例中突出顯示的錯誤。
查詢並避免未定義的行為
某些工具可用於在開發期間發現未定義的行為:
- 大多數編譯器都有警告標誌來警告編譯時某些未定義行為的情況。
- 較新版本的 gcc 和 clang 包含一個所謂的
Undefined Behavior Sanitizer
標誌(-fsanitize=undefined
),它將在執行時以效能成本檢查未定義的行為。 - 類似
lint
的工具可以執行更徹底的未定義行為分析。
未定義,未指定和實現定義的行為
從 C++ 14 標準(ISO / IEC 14882:2014)第 1.9 節(程式執行):
本國際標準中的語義描述定義了引數化的非確定性抽象機器。 [切]
抽象機的某些方面和操作在本國際標準中描述為實現定義的 (例如,
sizeof(int)
)。這些構成了抽象機器的引數。每個實施應包括描述其在這些方面的特徵和行為的檔案。 [切]抽象機器的某些其他方面和操作在本國際標準中被描述為未指定的 (例如,如果分配函式未能分配儲存器,則評估新初始化器中的表示式 )。在可能的情況下,本國際標準定義了一組允許的行為。這些定義了抽象機器的非確定性方面。因此,抽象機器的例項可以對給定程式和給定輸入具有多於一個可能的執行。
本國際標準中將某些其他操作描述為未定義 (或者,例如,嘗試修改
const
物件的效果)。 [ 注意 :本國際標準對包含未定義行為的程式的行為沒有要求。 - 結束說明 ]