文章目錄
如何擷取異常的詳細資料。
捕獲異常
//觸發異常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{ //釋放資源}
經測試完全正確!以前真不知道這樣也行。汗!非常感謝提醒!