回覆列表
  • 1 # 使用者963304282827

    提案裡把「錯誤」分成五類

    機器抽象被破壞:建議直接 terminate程式碼 bug:建議使用 Contracts(預設 terminate)OOM:建議用 new(nothrow) 和 try_ 系列函式可恢復的錯誤:建議拋異常或者返回錯誤碼部分成功:建議當作成功

    C/C++ 語言都是基於一臺抽象機器定義的,如果這樣的抽象被破壞根本沒得玩,只能退出。例子是「棧」耗盡:你不可能避免、也不可能解決。

    程式碼 bug 就是類似「前置條件不滿足」的情況,C/C++ 傳統上的處理辦法是「需要滿足某某條件,如果不滿足是未定義行為」(C++ 一度誤入 OO 歧途跟風搞出 std::invalid_argument 這種就讓它隨風而去吧),使用者程式碼一般推薦 assert。提案中建議統一交給 Contracts 處理我覺得非常好,因為這樣的函式不會涉及未定義行為,同時違反時會有明確的報錯資訊,對懶人友好。

    「部分成功」即類似「傳給 snprintf 的緩衝長度不夠用」這種,只要有良好的文件定義此時的行為,這種情況完全可以當作成功,而不是錯誤。

    剩下的兩個就是大頭:「異常 / 錯誤碼」和「OOM」。

    靜態異常是這個提案的大頭。

    說到底,沒有異常的 C++ 根本不是標準 C++,標準庫也依賴於異常。很多 C++ 工程和規範不接受異常,主要是因為:

    最終二進位制體積膨脹,同時執行時需要額外的空間和時間開銷執行時空間和時間開銷不確定

    新的 throws 函式 + std::error 的組合是披著異常外衣的錯誤碼,內在有點像 Swift 裡的一種錯誤彙報正規化:

    提案中的程式碼類似這樣

    std::error 可以理解為兩個指標,所以可以和正常的返回值共享同一個通道(甚至暫存器):

    payload:可以是錯誤碼,也可以是異常指標 exception_ptr。domain:類似 std::error_category 性質,區分不同領域的錯誤碼,可以是雜湊也可以是指標

    如果 throws 函式中有動態異常試圖越界,則透過某種機制對映為對應的 std::error,在 payload 中儲存該異常的指標。

    如果在普通函式中所呼叫的 throws 函式丟擲異常,則透過某種機制從 std::error 對映為對應的動態異常物件丟擲。

    這樣一來,靜態異常和普通的返回值無異,不再依賴堆分配、RTTI,只是語法上與「傳統」動態異常相似。同時還兼顧了已有程式碼,可以說是個非常不錯的解決方案了。

    You don"t pay for what you don"t use.When you do use it you can’t reasonably write it more efficiently by hand.

    最後說一下 OOM 吧。

    首先,我一直覺得「OOM 不可恢復」並不成立,這一點提案中也提到了「OOM 不等於記憶體耗盡,只是無法獲得指定大小的記憶體,請求 1T 記憶體失敗,換 1G 記憶體可能就成功了」。例如圖片解碼時 OOM 可以做 subsampling。

    提案中建議 new 失敗統一 terminate:

    如果需要舊行為可以替換 new handler 拋 std::bad_alloc如果需要自行處理可以用 new(nothrow)標準庫中提供 try_ 系列函式,例如 std::vector::reserve 對應 std::vector::try_reserve預設建構函式預設 noexcept

    我個人對此頗有微詞,非常希望這一部分得不到透過:

    自行替換 new handler:要求改全域性的東西總有種壞味道,也讓庫作者、呼叫者很為難new(nothrow):這種特殊化反而增加工作量,new 一個物件還得同時用兩種不同的錯誤處理機制處理問題(分別處理建構函式丟擲的異常和 new 返回的空指標)try_ 系列函式:又是「異常改錯誤碼」的變體,如果納入上文的 throws 函式範疇似乎更好

    有趣的是,提案中針對是否需要特殊化 OOM(是否需要區分開頭的第 3 和第 4 類錯誤)分別列舉了正反雙方觀點。不支援特殊化 OOM 的基本都是「既然一定是顯式申請的,如何處理應該由呼叫方決定」「有某某解決方案」這種客觀理由;支援特殊化 OOM 的理由在我看來大多很任性很諷刺:

    難處理、很多人處理錯了恢復需要額外的特殊處理(無法直面事實)(按:前面括號裡的內容不是我加的)某些情況下不可能發生這樣的錯誤你自己標準裡的解決方法就有不一致的地方直接忽略的話會帶來很多實現上的好處

    最後一點才是正經的理由,如果說實現上帶來方便最佳化等好處,特殊處理 OOM 似乎確實說得過去。而其它理由基本都只是在抱怨、逃避問題,非常欣賞作者的那個括號:無法直面事實。

  • 中秋節和大豐收的關聯?
  • 家裡新裝修油漆味重對小孩是不是有好大的影響呀?