編譯器如何知道C++常量計算不會觸發未定義的行為? [英] How do compilers know C++ constexpr computations do not trigger undefined behavior?

查看:0
本文介紹了編譯器如何知道C++常量計算不會觸發未定義的行為?的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

C++標準要求編譯器在C++常量計算中檢查未定義的行為。

this talk中,Chandler Carruth指出,在檢查UB時"您將耗盡檢測錯誤的能力",而且在一般情況下,檢測UB與halting problem相關,因此可以證明無法確定。

他指的不是conexpr中的UB,但conexpr計算從C++14開始就像常規程序一樣通用,因此這仍然適用。

那么,當編譯器無法確定程序是否是UB程序時,它們會做些什么?他們還會接受這個程序,祈禱自己繼續編譯嗎?或者,他們更加保守,拒絕接受這項計劃,即使它可能是正確的?(我個人的感覺是他們這樣做)

對我來說,這很重要,因為我用Clang編譯得很好的非平凡指針算法進行了常量計算,但用GCC編譯失敗了,我非常確定這不是UB。你可以說這是一個GCC的錯誤,但如果UB是無法決定的,那么所有的編譯器在這方面都是錯誤的。

更根本的是,為什么標準要求無UB?有沒有技術上的原因?或者更具哲理性的說法("如果編譯器不能檢查,程序員就會觸發UB,就會產生不好的結果")?

我認為這與C++的其余部分不一致,C++的其余部分永遠不會阻止您搬起石頭砸自己的腳。我寧愿GCC接受我的常量代碼并崩潰,或者如果是UB就發出垃圾;而不是當它不知道自己是不是UB時不編譯。

= 編輯=

正如M.M和Nicol Bolas所指出的,該標準規定了限制(甚至在C++14中),因此我們永遠不會遇到停頓問題類型的UB。然而,我仍然在想,檢查UB是否可能太復雜,如果編譯器啟發式失敗,那么他們會(可能不正確地)將其標記為非常量。

但我從評論中感覺到,這更多的是實現不成熟的問題。

推薦答案

在這次演講中,Chandler Carruth表示,在檢查UB時"您將耗盡檢測錯誤的能力",而且在一般情況下,檢測UB與停止問題有關,因此可以證明不可能做出決定。

暫停的問題是,當您獲取一個程序并嘗試確定該程序在執行時是否一定會暫停。根據定義,停止問題僅將程序視為鎖定對象。

持續評估是...評估。您正在執行程序,而不僅僅是查看源代碼。

當程序的執行執行某些未定義的操作時,會發生未定義的行為。大多數UB案例不能確定是明確定義的,也不能僅僅通過檢查源代碼來確定。請考慮以下代碼:

void foo(void *ptr)
{
  *reinterpret_cast<int*>(ptr) = 20;
}

那是不是UB?這要視情況而定;如果將指向int的指針傳遞到foo中,那么它將是定義良好的。此代碼是否定義良好只能由執行方式確定。

常量計算需要執行代碼;這就是我們通常將其稱為編譯時執行的原因。當您執行代碼時,可以知道foo的特定執行是否傳遞了指向實際int的指針(忽略reinterpret_castconstexpr代碼中被禁止的事實)。因此,在評估時,您可以知道是否發生了UB。

那么,當編譯器無法確定程序是否是UB程序時,他們該怎么辦?

這實際上不是一件可能發生的事情。假設規范是完整的并且沒有漏洞,程序的執行是否表現出定義良好的行為僅僅是遵循規范的問題。

您與GCC和Clang之間的問題不是能否確定UB的問題。

更根本的是,為什么標準要求不含UB?是否有技術原因?

假設,我們可以從C++甚至C中刪除所有未定義的行為。我們可以讓一切都是先驗定義的,并從語言中刪除其計算結果不能從基本原則中確定的任何內容。

標準不會這樣做,因為這會很糟糕。它會阻止我們做各種有用的、低級的事情。它將阻止有用的編譯器優化。以此類推。

這些原因都不適用于編譯時代碼執行。尤其是"有用的、低級的東西"這一部分。對于編譯后的代碼,生成的代碼在一臺實際的機器上執行。因此,有一個后門來與真實的機器對話是有意義的。然而,在編譯時,沒有真正的機器可供對話;只有C++定義的抽象機器。那么允許UB有什么意義呢?

編譯器不會生成并執行機器語言;常量求值基本上是在編譯器內執行腳本語言。與大多數腳本語言一樣,您希望它能夠安全而正確地進行計算。您希望快速捕獲錯誤(UB是錯誤),并在故障點提供干凈的錯誤消息,而不是在過程中隨意死亡。

這篇關于編譯器如何知道C++常量計算不會觸發未定義的行為?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持IT屋!

查看全文
登錄 關閉
掃碼關注1秒登錄
發送“驗證碼”獲取 | 15天全站免登陸
全免费A级毛片免费看无码播放