C# 捕獲異常詳情

轉載自[ http://www.cnblogs.com/zjfree/ ]

捕獲異常

//觸發異常
private void test()
{
    int i = 0;
    i = 12 / i;
}
  
//直接捕獲異常
private void button1_Click(object sender, EventArgs e)
{
    try
    {
        test();
    }
    catch (Exception ex)
    {
        this.textBox1.Text = ex.ToString();
    }
}

錯誤信息:

System.DivideByZeroException: 試圖除以零。
   在 ExceptionTest.Form1.test() 位置 C:\Documents and Settings\Administrator\桌面\ExceptionTest\Form1.cs:行號 25
   在 ExceptionTest.Form1.button1_Click(Object sender, EventArgs e) 位置 C:\Documents and Settings\Administrator\桌面\ExceptionTest\Form1.cs:行號 33

通過錯誤信息可以發現提示信息顯示錯誤行是 i = 12 / i; 這行。

捕獲異常問題

而實際上我們有可能捕獲異常後處理完成後會在將異常拋給調用程序

//間接捕獲異常
private void button2_Click(object sender, EventArgs e)
{
    try
    {
        test1();
    }
    catch (Exception ex)
    {
        this.textBox1.Text = ex.ToString();
    }
}
  
private void test1()
{
    try
    {
        test();
    }
    catch (Exception ex)
    {
        //錯誤處理...
  
        throw ex;
    }
}

錯誤信息:

System.DivideByZeroException: 試圖除以零。
   在 ExceptionTest.Form1.test1() 位置 C:\Documents and Settings\Administrator\桌面\ExceptionTest\Form1.cs:行號 63
   在 ExceptionTest.Form1.button2_Click(Object sender, EventArgs e) 位置 C:\Documents and Settings\Administrator\桌面\ExceptionTest\Form1.cs:行號 46

通過錯誤信息可以發現提示信息顯示錯誤行是 throw ex;這行。
根據如上的錯誤提示是很難發現根本錯誤原因的。爲什麼沒有提示i = 12 / i;行錯誤呢?
是因爲代碼已經使用try catch將除零錯誤捕獲,捕獲後又拋出了此異常!又被外層函數捕捉後,錯誤中就只留下了throw時的錯誤行信息。

那如何纔可以獲取具體的異常呢?

//解決方法
private void button3_Click(object sender, EventArgs e)
{
    try
    {
        test2();
    }
    catch (Exception ex)
    {
        this.textBox1.Text = ex.ToString();
    }
}
  
private void test2()
{
    try
    {
        test();
    }
    catch (Exception ex)
    {
        //自定義異常
        throw new Exception("出錯啦!", ex);
    }
}

錯誤信息:

System.Exception: 出錯啦! ---> System.DivideByZeroException: 試圖除以零。
   在 ExceptionTest.Form1.test() 位置 C:\Documents and Settings\Administrator\桌面\ExceptionTest\Form1.cs:行號 25
   在 ExceptionTest.Form1.test2() 位置 C:\Documents and Settings\Administrator\桌面\ExceptionTest\Form1.cs:行號 84
   --- 內部異常堆棧跟蹤的結尾 ---
   在 ExceptionTest.Form1.test2() 位置 C:\Documents and Settings\Administrator\桌面\ExceptionTest\Form1.cs:行號 89
   在 ExceptionTest.Form1.button3_Click(Object sender, EventArgs e) 位置 C:\Documents and Settings\Administrator\桌面\ExceptionTest\Form1.cs:行號 72

因爲throw new Exception("出錯啦!", ex); 重新創建了新的自定義異常,並且將原始異常設置爲innerException;所以異常信息中包含了多個層次的異常信息。

關於異常在DEBUG RELEASE版的差異。

以上異常信息是在DEBUG模式下。
DEBUG RELEASE在VS調試狀態下獲取結果相同。
當在RELEASE獨立運行時
RELEASE模式下 無ExceptionTest.pdb
System.Exception: 出錯啦!
---> System.DivideByZeroException: 試圖除以零。
   在 ExceptionTest.Form1.test2() 
  --- 內部異常堆棧跟蹤的結尾 ---
   在 ExceptionTest.Form1.test2()
   在 ExceptionTest.Form1.button3_Click(Object sender, EventArgs e)
RELEASE模式下
System.Exception: 出錯啦!
---> System.DivideByZeroException: 試圖除以零。
   在 ExceptionTest.Form1.test2() 位置 C:\Documents and Settings\Administrator\桌面\ErrorLog\ExceptionTest\Form1.cs:行號 84
   --- 內部異常堆棧跟蹤的結尾 ---
   在 ExceptionTest.Form1.test2() 位置 C:\Documents and Settings\Administrator\桌面\ErrorLog\ExceptionTest\Form1.cs:行號 89
   在 ExceptionTest.Form1.button3_Click(Object sender, EventArgs e) 位置 C:\Documents and Settings\Administrator\桌面\ErrorLog\ExceptionTest\Form1.cs:行號 72 

總結

注意在捕獲並拋出異常時應使用 throw new Exception("出錯啦!", ex); 方式,則可獲得異常的具體位置。

當在VS調試或者DEBUG模式下運行程序成都可獲得異常發生的具體位置。

但當在獨立運行的RELEASE模式下時,異常只會記錄最初的調用位置。

當執行目錄不包含 *.pdb 文件時,異常信息中不會包含代碼及行號信息。

測試代碼下載

下載:http://files.cnblogs.com/zjfree/ErrorLog.rar

環境:WIN2003 + VS2005 + C#

補充

經園友 孤劍 指正!catch 了異常後,如果不處理,直接寫 throw 即可,不用 throw ex; 示例如下:

try
{
    test();
}
catch
{
    //異常處理
    throw;
}

而對於無須異常處理的情況,寫法如下:

try
{
    test();
}
finally
{
    //釋放資源
}

經測試完全正確!以前真不知道這樣也行。汗!非常感謝提醒!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章