簡體   English   中英

是否應該捕獲異常

[英]Should exceptions ever be caught

毫無疑問,異常是有用的,因為它們向程序員顯示他正在使用不正確的函數或者在環境中發生了一些不好的事情但是真的需要捕獲它們嗎?

未捕獲的異常將終止程序,但您仍然可以看到問題出在哪里。 在設計良好的庫中,每種“意外”情況實際上都可以解決。 例如,使用map::find而不是map::at ,在使用索引運算符之前檢查int變量是否小於vector::size

為什么有人需要這樣做(不包括使用強制實施該程序的庫的人)? 基本上,如果您要為給定的異常編寫處理程序,則還可以編寫代碼以防止其發生。

並非所有例外都是致命的。 它們可能不常見,因此也可能是“異常”,但調用堆棧中的高點可以實現重試或繼續。 通過這種方式,異常用於展開堆棧和嵌套的一系列函數或方法調用程序中的一個點,它實際上可以處理異常的原因 - 即使只是為了清理一些資源,記錄錯誤,並繼續像以前一樣。

您不能總是編寫阻止異常的代碼。 僅舉一個明顯的例子,考慮並發代碼。 假設我嘗試驗證i在(例如)0到20之間,然后使用i索引到某個數組。 所以,我檢查並且i == 12 ,所以我繼續使用它來索引數組。 不幸的是,在測試和索引操作之間,一些其他線程將i添加到20,所以當它被用作索引時,它不再在范圍內了。

並發導致了競爭狀況,因此針對異常狀況進行保證的嘗試失敗了。 雖然可以通過(例如)將每個這樣的測試/使用序列包裝在關鍵部分(或類似部分)中來防止這種情況,但這樣做通常是不切實際的 - 首先,獲得正確的代碼通常會非常困難,甚至是第二次如果正確,則對執行速度的影響可能是不可接受的。

異常還會將檢測到異常情況的代碼與響應該異常情況的代碼分離。 這就是為什么異常處理如此受到庫編寫者的歡迎。 庫中的代碼沒有關於對特定異常情況作出反應的正確方法的線索。 僅舉一個非常簡單的例子,讓我們假設它無法從文件中讀取。 它應該將消息打印到stderr ,彈出MessageBox還是寫入日志?

實際上,它不應該做這些。 對於任何給定的程序,至少有兩個(可能是全部三個)是錯誤的。 因此,它應該做的是拋出一個異常,然后讓更高級別的代碼確定適當的響應方式。 對於一個程序,記錄錯誤並繼續其他工作可能是有意義的,但對於另一個程序,該文件可能足夠關鍵,其唯一合理的反應是完全中止執行。

例外是非常昂貴的,性能差異 - 因此,無論何時性能問題,您都希望編寫一個免除異常的代碼(使用“普通C”技術進行錯誤傳播)。

但是,如果性能不是直接關注的話,那么異常將允許您開發一個不那么雜亂的代碼,因為可以推遲錯誤處理(但是那時你將不得不處理非本地控制轉移,這本身可能會造成混淆)。

我已經使用了廣泛的例外作為根據事件處理轉移對特定位置的控制的方法。 例外也可以是將控制轉移到調用函數樹的“標記”位置的方法。 當異常發生時,代碼可以被認為是一次回溯一個級別並檢查該級別是否具有活動的異常並執行它。

異常的真正問題是你真的不知道這些會發生在哪里。 到達異常的代碼通常不知道為什么會出現問題,因此快速返回已知狀態是一個很好的操作。 讓我們舉個例子:您在威尼斯,看着在小路上行走的地圖,此刻到達了您在地圖上找不到的地方。 基本上你很困惑,你不明白你在哪里。 如果您有ariadne“μιτος”,您可以回到已知點並重新啟動以嘗試到達您想要的位置。

我認為你應該只將錯誤處理視為一種控制結構,允許在任何級別上返回信號(通過錯誤處理例程和錯誤代碼)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM