Pao*_*sco 18 c# exception stack-trace
如果在switch
语句中抛出异常,我注意到异常堆栈跟踪中的行号有奇怪的行为.
这是一个例子(格式当然是因为行号):
using System;
class Program {
static void Main(string[] args) {
for (int i = 0; i < 3; i++) {
try {
ThrowSomeException(i);
} catch (Exception exc) {
Console.WriteLine(exc);
}
}
}
private static void ThrowSomeException(int arg) {
Console.WriteLine("arg = {0}", arg);
switch (arg) {
case 0:
throw new Exception("Line number = 16");
case 1:
throw new Exception("Line number = 18");
default:
throw new Exception("Line number = 20");
}
}
}
Run Code Online (Sandbox Code Playgroud)
堆栈跟踪中报告的行是switch语句中下一个异常的行.上面的程序产生了这个结果(注意异常文本中的行号与堆栈跟踪中的行号不匹配):
arg = 0
System.Exception: Line number = 16
at Program.ThrowSomeException(Int32 arg) in x:\test\Program.cs:line 18
at Program.Main(String[] args) in x:\test\Program.cs:line 6
arg = 1
System.Exception: Line number = 18
at Program.ThrowSomeException(Int32 arg) in x:\test\Program.cs:line 20
at Program.Main(String[] args) in x:\test\Program.cs:line 6
arg = 2
System.Exception: Line number = 20
at Program.ThrowSomeException(Int32 arg) in x:\test\Program.cs:line 20
at Program.Main(String[] args) in x:\test\Program.cs:line 6
Run Code Online (Sandbox Code Playgroud)
为什么会这样?
注意:我在VS 2012和2013上都试过这个,在.NET 3.5和4.5上都进行了编译,得到了相同的结果.
调试与发布:令人惊讶的是,我只在Debug中遇到这种奇怪的行为,在Release中,行号是正确的.
我尝试过反编译程序集,似乎程序集在任一模式下都进行了一些优化。特别是第二种方法发生了变化:
private static void ThrowSomeException(int arg)
{
Console.WriteLine("arg = {0}", arg);
switch (arg)
{
case 0:
{
throw new Exception("Line number = 16");
}
case 1:
{
throw new Exception("Line number = 18");
}
}
throw new Exception("Line number = 20");
}
Run Code Online (Sandbox Code Playgroud)
这就是 Telerik JustDecompile 告诉我该方法在调试和发布模式下的样子。如果您查看原始程序集,很可能会进一步解释为什么存在这种差异。
我不知道如何继续这个,但我认为这是一个非常有趣的问题。我将把我的答案标记为社区维基,希望通过协作努力可以解决这个问题。
我做了更多测试。我已将 ThrowSomeException() 函数移至一个单独的类并使其成为非静态的,但这并没有改变任何内容。然后我稍微重写了它,首先将异常分配给一个变量,然后单独抛出它。
internal class Program
{
private static void Main()
{
Test test = new Test();
for (int i = 0; i < 3; i++)
{
try
{
test.ThrowSomeException(i);
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
}
}
public class Test
{
public void ThrowSomeException(int arg)
{
Console.WriteLine("arg = {0}", arg);
switch (arg)
{
case 0:
{
Exception ex = new Exception("Line number = 36");
throw ex;
}
case 1:
{
Exception ex = new Exception("Line number = 41");
throw ex;
}
default:
{
Exception ex = new Exception("Line number = 46");
throw ex;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码在调试模式下有以下输出:
arg = 0
System.Exception: Line number = 36
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 40
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 14
arg = 1
System.Exception: Line number = 41
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 45
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 14
arg = 2
System.Exception: Line number = 46
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 47
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 14
Run Code Online (Sandbox Code Playgroud)
在Release模式下,第二个异常是从第46行而不是第45行抛出的。此行为对于所有版本的.NET框架和所有版本的VS都是一致的。接下来我将尝试使用 VB 项目来执行此操作,看看是否会有所不同。
编辑:在 VS 2012 中使用以下 VB 项目:
Module Program
Sub Main()
Dim test As New Test()
For i As Integer = 0 To 2
Try
test.ThrowSomeException(i)
Catch exception As Exception
Console.WriteLine(exception)
End Try
Next
End Sub
End Module
Public Class Test
Public Sub ThrowSomeException(arg As Integer)
Console.WriteLine("arg = {0}", arg)
Select Case arg
Case 0
If True Then
Dim ex As New Exception("Line number = 22")
Throw ex
End If
Case 1
If True Then
Dim ex As New Exception("Line number = 27")
Throw ex
End If
Case Else
If True Then
Dim ex As New Exception("Line number = 32")
Throw ex
End If
End Select
End Sub
End Class
Run Code Online (Sandbox Code Playgroud)
没有出现该问题,并且行号一致。
我还测试了直接输出生成的可执行文件,发现了更奇怪的结果。这是调试 exe 的输出:
arg = 0
System.Exception: Line number = 36
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 40
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 14
arg = 1
System.Exception: Line number = 41
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 45
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 14
arg = 2
System.Exception: Line number = 46
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 47
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 14
Run Code Online (Sandbox Code Playgroud)
这是发布模式 exe 的输出:
arg = 0
System.Exception: Line number = 36
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 41
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 14
arg = 1
System.Exception: Line number = 41
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 42
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 14
arg = 2
System.Exception: Line number = 46
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 37
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 14
Run Code Online (Sandbox Code Playgroud)
这与使用调试器运行它的结果不同。
快速测试似乎表明异常和 throw 语句之间的额外行(在本例中 console.writeline() 也会影响结果:
改写为:
switch (arg)
{
case 0:
{
Exception ex = new Exception("Line number = 37");
Console.WriteLine("case 0");
throw ex;
}
case 1:
{
Exception ex = new Exception("Line number = 43");
Console.WriteLine("case 1");
throw ex;
}
default:
{
Exception ex = new Exception("Line number = 49");
Console.WriteLine("case default");
throw ex;
}
}
Run Code Online (Sandbox Code Playgroud)
给出 VS 的 Release 输出:
arg = 0
case 0
System.Exception: Line number = 37
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 43
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
arg = 1
case 1
System.Exception: Line number = 43
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 49
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
arg = 2
case default
System.Exception: Line number = 49
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 51
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
Run Code Online (Sandbox Code Playgroud)
以及命令行的输出:
arg = 0
case 0
System.Exception: Line number = 37
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 43
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
arg = 1
case 1
System.Exception: Line number = 43
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 45
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
arg = 2
case default
System.Exception: Line number = 49
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 39
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
Run Code Online (Sandbox Code Playgroud)
VS 的调试输出:
arg = 0
case 0
System.Exception: Line number = 37
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 42
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
arg = 1
case 1
System.Exception: Line number = 43
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 48
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
arg = 2
case default
System.Exception: Line number = 49
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 51
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
Run Code Online (Sandbox Code Playgroud)
命令行的输出如下:
arg = 0
case 0
System.Exception: Line number = 37
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 42
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
arg = 1
case 1
System.Exception: Line number = 43
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 48
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
arg = 2
case default
System.Exception: Line number = 49
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 51
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1059 次 |
最近记录: |