問題描述
我有這個代碼
try
{
//AN EXCEPTION IS GENERATED HERE!!!
}
catch
{
SqlService.RollbackTransaction();
throw;
}
上面的代碼在這段代碼中被調用
Code above is called in this code
try
{
//HERE IS CALLED THE METHOD THAT CONTAINS THE CODE ABOVE
}
catch (Exception ex)
{
HandleException(ex);
}
作為參數傳遞給方法HandleException"的異常包含堆棧跟蹤中throw"行的行號,而不是生成異常的實際行.有誰知道為什么會發生這種情況?
The exception passed as parameter to the method "HandleException" contains the line number of the "throw" line in the stack trace instead of the real line where the exception was generated. Anyone knows why this could be happening?
EDIT1好的,謝謝大家的回答.我把內扣換成了
EDIT1 Ok, thanks to all for your answers. I changed the inner catch for
catch(Exception ex)
{
SqlService.RollbackTransaction();
throw new Exception("Enrollment error", ex);
}
現在我在堆棧跟蹤中有正確的行,但我必須創建一個新異常.我希望找到更好的解決方案:-(
Now I have the correct line on the stack trace, but I had to create a new exception. I was hoping to find a better solution :-(
EDIT2也許(如果你有 5 分鐘的時間)你可以嘗試這個場景來檢查你是否得到相同的結果,重新創建不是很復雜.
EDIT2 Maybe (if you have 5 minutes) you could try this scenario in order to check if you get the same result, not very complicated to recreate.
推薦答案
是的,這是異常處理邏輯的限制.如果一個方法包含多個拋出異常的 throw 語句,那么您將獲得最后一個拋出異常的行號.此示例代碼重現了此行為:
Yes, this is a limitation in the exception handling logic. If a method contains more than one throw statement that throws an exception then you'll get the line number of the last one that threw. This example code reproduces this behavior:
using System;
class Program {
static void Main(string[] args) {
try {
Test();
}
catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
Console.ReadLine();
}
static void Test() {
try {
throw new Exception(); // Line 15
}
catch {
throw; // Line 18
}
}
}
輸出:
System.Exception: Exception of type 'System.Exception' was thrown.
at Program.Test() in ConsoleApplication1Program.cs:line 18
at Program.Main(String[] args) in ConsoleApplication1Program.cs:line 6
解決方法很簡單,只需使用輔助方法來運行可能引發異常的代碼.
The work-around is simple, just use a helper method to run the code that might throw an exception.
像這樣:
static void Test() {
try {
Test2(); // Line 15
}
catch {
throw; // Line 18
}
}
static void Test2() {
throw new Exception(); // Line 22
}
這種尷尬行為的根本原因是 .NET 異常處理建立在操作系統對異常的支持之上.稱為 SEH,Windows 中的結構化異常處理.這是基于堆棧幀的,每個堆棧幀只能有一個活動異常..NET 方法有一個堆棧幀,與方法內的范圍塊數量無關.通過使用輔助方法,您可以自動獲得另一個可以跟蹤其自身異常的堆棧幀.當方法包含 throw 語句時,抖動還會自動抑制內聯優化,因此無需顯式使用 [MethodImpl] 屬性.
The underlying reason for this awkward behavior is that .NET exception handling is built on top of the operating system support for exceptions. Called SEH, Structured Exception Handling in Windows. Which is stack-frame based, there can only be one active exception per stack frame. A .NET method has one stack frame, regardless of the number of scope blocks inside the method. By using the helper method, you automatically get another stack frame that can track its own exception. The jitter also automatically suppresses the inlining optimization when a method contains a throw statement so there is no need to explicitly use the [MethodImpl] attribute.
這篇關于堆棧跟蹤上的錯誤行號的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!