问题描述
我有这个代码
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.
这篇关于堆栈跟踪上的错误行号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!