D 中的錯誤處理 2 014

2021-08-29 14:33:05 字數 2883 閱讀 2450

無版本差異

我來了,我編碼了,我崩潰了。-- julius c'ster

所有的程式都要應付錯誤。錯誤是不在程式正常操作範圍內的異常情況:常見的錯誤情況

有:• 記憶體耗盡。

• 磁碟空間耗盡。

• 檔名無效。

• 試圖寫唯讀檔案。

• 試圖讀不存在的檔案。

• 請求不支援的系統服務。

21.1 錯誤處理問題

c 語言檢測報告錯誤的傳統方法並沒形成傳統,每個函式都有自己的方法,包括:

• 返回 null 指標。

• 返回 0 值。

• 返回非零的錯誤**。

• 需要檢查 errno。

• 如果上述檢查失敗了,需要呼叫乙個函式。

為了處理可能出現的錯誤,必須為每個函式新增繁瑣的錯誤處理**。如果發生了錯誤,必

須有錯誤恢復**,並且需要有**將錯誤以某種友好的方式告訴給使用者。如果不能在發生

錯誤的區域性環境處理錯誤,就必須顯式地將錯誤傳播給它的呼叫者。如果要顯示錯誤型別,

需要將一大堆 errno 值轉換為合適的文字。這些**可能占用整個專案編碼時間的一大部

分,而且如果執行時系統加入了乙個新的 errno 值,舊有的**就不能顯示有意義的資訊。

功能良好的錯誤處理**很容易將清晰而簡潔的實現搞得一團糟。

更糟的是,功能良好的錯誤處理**本身就很容易出錯,還總是整個專案中測試最不充分的

部分(因此充滿錯誤),並且還總是被簡單地省略。最終的結果就如同「藍屏宕機」那樣,

程式由於無法處理一些未預料到的錯誤而失敗。

並不值得為「快速而髒的(quick and dirty)」程式編寫錯誤處理**,因此使用這類程式就好

像使用沒有鋸罩的多功能台式電鋸。

我們所需要的是如下的錯誤處理哲學和方法學:

• 標準化——如果用法一致,它就更有用。

• 就算程式設計師無法查出出現了什麼錯誤,也要使程式以合適的方式終止。

• 在無需改動舊**的前提下就可以加入新的錯誤型別,從而重用舊的**。

• 不會由於粗心大意而忽略某些錯誤。

• 重寫「快速而髒的」程式直到能夠正確處理錯誤。

• 可以很容易地寫出清晰的錯誤處理**。

197第 21 章 d 中的錯誤處理 — 張雪平

21.2 d 的錯誤處理解決方案

先讓我們觀察一下並對錯誤作出以下假設:

• 錯誤不屬於正常的程式流。錯誤是異常的、不常見的、不該出現的。

• 因為錯誤不常見,所以錯誤處理**的效能並不十分重要。

• 程式的正常邏輯流的效能很關鍵。

• 所有的錯誤必須採用統一的方式處理,不論是顯式地編寫**處理它們還是採用系統

預設的處理方式。

息。解決方案是使用異常處理來報告錯誤。所有的錯誤都是從抽象類 error 派生的物件。error

類有乙個叫做 tostring() 的純虛函式,它返回乙個 char 型別的人類可讀的錯誤描述。

如果**檢測到了乙個錯誤,如「記憶體耗盡」,則丟擲 error 物件,其中包含訊息「記憶體耗

盡」。函式呼叫堆疊會被展開,並查詢 error 的處理程式。隨著堆疊的展開,相應的

finally 塊 會被執行。如果找到了錯誤處理程式,就在該處恢復程式的執行。否則,會執行

預設的錯誤處理程式,該程式會顯示錯誤訊息並終止程式。

這個解決方案是否能滿足我們的要求?

標準化——如果用法一致,它就更有用。

這正是 d 的方法,d 執行時庫和示例都採用這種方式。

就算程式設計師無法查出出現了什麼錯誤,也要使程式以合適的方式終止。

如果沒有相應的錯誤處理程式,程式會執行預設的錯誤處理程式,該處理程式列印出

適當的訊息,並使程式優雅的推出。

在無需改動舊**的前提下就可以加入新的錯誤型別,從而重用舊的**。

舊的**可以決定是捕獲所有的錯誤,或者是只捕獲特定的錯誤並向上傳播剩餘的錯

誤。無論那種情況,都不必為每個錯誤**關聯乙個訊息了,編譯器會自動為其提供

正確的訊息。

不會由於粗心大意而忽略某些錯誤。

異常會採用這種或那種方式處理。不會出現使用 null 指標表示出錯,但後面的**

卻試圖使用該 null 指標的情況。

重寫「快速而髒的」程式直到能夠正確處理錯誤。

「快速而髒的」**根本不需要包含任何錯誤處理**,也不需要檢查錯誤。錯誤會

被預設的處理程式捕獲,顯示適當的訊息,然後程式會優雅的終止。

可以很容易地寫出清晰的錯誤處理**。

try/catch/finally 語句比那些無窮無盡的 if (出錯) goto 處理程式; 語句要清晰得多。

這個解決方案是否符合我們對於的錯誤的假設?

錯誤不屬於正常的程式流。錯誤是異常的、不常見的、不該出現的。

d 的異常處理機制完全符合上述假定。

因為錯誤不常見,所以錯誤處理**的效能並不十分重要。

異常處理堆疊的展開相對較慢。

198第 21 章 d 中的錯誤處理

程式的正常邏輯流的效能很關鍵。

因為正常的**流不必檢查每個函式呼叫的返回值是否代表出錯,使用異常處理來處

理錯誤確實會使程式執行得更快。

所有的錯誤必須採用統一的方式處理,不論是顯式地編寫**處理它們還是採用系統預設的

處理方式。

如果某個錯誤沒有對應的處理程式,就會由執行時庫中的預設處理程式處理。如果一

個錯誤被忽略了,那一定是程式設計師特意新增了**用於忽略這個錯誤,因此這一定是

在程式設計師意料之中的。

不需要將錯誤**翻譯為人類可讀的字串,錯誤檢測**而不是錯誤恢復**負責

生成正確的字串。這種做法也使不同的程式出現相同的錯誤時會輸出相同的訊息。

使用異常來處理錯誤會導致其它的問題——如何寫出異常安全的程式。這裡有關於怎麼做的

說明。

D語言中的錯誤處理

所有的程式都要應付錯誤。錯誤是不在程式正常操作範圍內的異常情況 c 語言檢測報告錯誤的傳統方法並沒形成傳統,每個函式都有自己的方法,包括 為了處理可能出現的錯誤,必須為每個函式新增繁瑣的錯誤處理 如果發生了錯誤,必須有錯誤恢復 並且需要有 將錯誤以某種友好的方式告訴給使用者。如果不能在發生錯誤的區域...

MySql錯誤處理 錯誤處理的例子

有幾種錯誤處理的宣告形式 如果任何錯誤 不是 not found 設定 l error 為 1 後繼續執行 declare continue handler for sqlexception set l error 1 如果發生任何錯誤 不是 not found 執行 rollback和產生一條錯誤...

swift 中錯誤處理

enum customerror error 定義乙個測試用的類 class testerrorclass name s func showstring 第一種使用方式,執行 後,直接丟擲異常,中止執行 let tes trytesterrorclass s 執行結果 lldb expr 123.c...