2008-12-09 200 views
1

結構化異常處理不好嗎?什麼是處理異常的正確方法?異常處理

編輯:在.NET中使用C#的異常處理。

我通常有一組特定的異常類(DivideByZeroException,ArrayTypeMismatchException)並且沒有泛型「catch(Exception ex)」。

這個背後的思想是,我期望發生某些類型的異常,並在發生異常時定義特定的操作,並且意外的異常會升起界面(無論是Windows還是Web)。這是一個很好的做法嗎?

+0

「結構化」是什麼意思? – 2008-12-09 14:33:03

+0

如果你提到了一種語言,這將是一件好事,所以我們可以在詳細和更好的情況下幫助你。 – GEOCHET 2008-12-09 14:33:06

回答

3

捕獲語句+堆棧跟蹤。在沒有打印堆棧跟蹤的情況下,如果沒有捕獲到異常,您或其他人將不得不再次檢出該代碼,並在發生錯誤並且日誌文件爲空或模糊時在Catch塊中放置堆棧跟蹤。

5

我不確定'結構化異常處理'是什麼意思。

在異常處理中可以做的最糟糕的事情是「吞下」異常或者靜靜地處理異常。

不這樣做:

try { 
    ... 
} 
catch (Exception e) { 
    //TODO: handle this later 
} 

這是很經常做出於懶惰讓代碼編譯。如果您不知道如何處理特定級別的異常,請讓該方法拋出異常,並且至少在頂部有一個catch all handler。以某種方式提供反饋(通過GUI,頁面/電子郵件發送給支持人員,日誌文件),以便問題最終得到解決。默默地捕捉異常幾乎總是會導致稍後發生更大的問題,並且難以追蹤。

1

我的建議:

不要捕捉異常,除非:

  • 如果不這樣做會導致應用程序崩潰(例如,在事件處理程序)
    • 而在這的情況下,一定要記錄異常,以便您知道發生了什麼事情以及何時發生什麼事情
  • 您可以對t並糾正這種情況(例如在調用偶爾會拋出異常的外部API時實現重試機制(請注意,不應該使用異常處理來控制程序流))
    • 而在這種情況下,只捕獲您希望獲得的特定異常類型拋出

捕獲在儘可能高的水平異常意味着你得到最大的調用堆棧,當你經歷的日誌,並想看看初始動作觸發的序列,這是非常有用的首先導致例外的事件。

1

這是一個複雜的話題......有這方面的書......但......有兩種主要的異常處理類型......內聯,其中處理潛在錯誤的代碼與方法或例程將「正常」執行的代碼以及結構化異常處理(其中代碼位於其他地方)以及基礎結構被設計爲自動處理該異常處理代碼意外事件(錯誤)發生......兩者都有優勢和劣勢。 「內聯」方法傾向於產生更加混亂的代碼(帶有錯誤代碼),難以閱讀和維護。但是,由於它不需要任何前期分析,所以它更容易生成。使用內聯錯誤處理時,您經常會看到方法返回布爾值或數字「錯誤」代碼,向調用方指明metjhod或例程是否成功。這消除了使例程「返回」有意義的業務價值或對象的「功能」語法(因爲按慣例每個函數都必須返回錯誤代碼)。使用結構化異常處理時,此問題沒有實際意義。

結構化異常處理otoh通常很難做好,因爲它需要事先分析例程或方法可能產生的錯誤以及該方法可以或應該對每個錯誤執行什麼操作if它確實發生。

有一兩件事是肯定的,不要在單一成分的兩種方法混合...

0

我不是一個Windows程序員,但在使用結構化異常處理處理硬件異常之類的軟件在我看來,例外意味着:

  • 您的代碼在C++標準中產生了一些未定義或實現定義的行爲(例如除以零)。
  • Windows定義在啓用SEH的情況下,它會在此情況下引發異常。
  • 您正在使用這個事實來捕獲異常和/或執行終止處理程序。

所以問題要問,IMO,主要有:

  • 是您的編程任務真正性質,即標準C++不能處理的? (或者只能通過明顯低於硬件異常的方式來處理)。
  • 當你的代碼變得非標準時你真的需要採取行動嗎?
  • 您可以編寫代碼,以便它不會首先引發硬件異常?

如果答案爲'是','是','否',則需要結構化的異常處理。否則,你可能可以避免它,在這種情況下,你可能想要。編寫異常安全的代碼非常棘手,所以異常保證越強大,你越能提供更好的結果。可能與SEH劃分爲零的代碼不提供不保證,或許在重新設計時可能會導致呼叫者不提供數據,但可以這樣做。但是如果一個函數由於其他原因而必須拋出異常,那麼也可能將它們丟給硬件陷阱,這可能會讓事情變得更糟。

一個值得注意的特例是內存分配。不確定.NET是否這樣做,但是如果分配的虛擬地址空間不足,則Linux分配只會失敗。物理內存在第一次使用時被提交,如果沒有足夠的硬件,會導致硬件異常。由於內存分配是假定在發生故障時拋出std :: bad_alloc,並且實現未能實現此標準的這一要求,所以可能是是因爲在某些情況下將硬件異常轉換爲軟件是正確的。但是,這種硬件異常可能會發生在意想不到的地方(包括您認爲不太合適的例程),所以仍然可能無法妥善處理,這就是爲什麼linux核心轉儲而不是拋出。在實踐中,完全初始化的任何東西都會導致其構造函數崩潰,這通常足夠接近分配,而軟件異常會變得有用。