为什么有时不能正确定位到异常的发生位置?
在我们定位异常发生位置的时候,一般都能得到正确的异常信息(Exception.Message)。
但是当根据调用堆栈来定位异常发生点的时候,却往往得不到正确的位置,即正确的调用堆栈。
这与再次抛出异常的方式有关,请看下面的程序和输出结果。
在foo_ABC中捕获、处理、并重新抛出异常。在Main函数中最终来处理异常,获得详细的异常信息。
当使用 throw ex 后,在异常的调用堆栈里就不是正确正确的异常发生位置。
如果有源代码则可以顺着继续找,如果没有的话,则不好正确定位异常的发起的根源。
结论:
异常的调用堆栈,是以发生异常或者throw ex为起点的,当使用throw ex时会覆盖掉发生异常时产生的调用堆栈。
所以, foo_A()函数里抛出异常的方式要慎用!
2
3 namespace ConsoleApplication18
4 {
5 /// <summary>
6 /// Summary description for Class1.
7 /// </summary>
8 class Class1
9 {
10 /// <summary>
11 /// The main entry point for the application.
12 /// </summary>
13 [STAThread]
14 static void Main(string[] args)
15 {
16 try
17 {
18 foo_A();
19 }
20 catch(Exception ex)
21 {
22 Console.WriteLine("=================Main");
23 Console.WriteLine(ex.ToString());
24 Console.WriteLine("");Console.WriteLine("");
25 }
26
27 try
28 {
29 foo_B();
30 }
31 catch(Exception ex)
32 {
33 Console.WriteLine("=================Main");
34 Console.WriteLine(ex.ToString());
35 Console.WriteLine("");Console.WriteLine("");
36 }
37
38 try
39 {
40 foo_C();
41 }
42 catch(Exception ex)
43 {
44 Console.WriteLine("=================Main");
45 Console.WriteLine(ex.ToString());
46 Console.WriteLine("");Console.WriteLine("");
47 }
48
49 int i = Console.Read();
50 }
51
52 private static void foo()
53 {
54 throw new Exception("happend in foo");
55 }
56
57 private static void foo1()
58 {
59 foo();
60 }
61
62 private static void foo_A()
63 {
64 try
65 {
66 foo1();
67 }
68 catch(Exception ex)
69 {
70 Console.WriteLine("=================foo_A throw ex;");
71 Console.WriteLine(ex.ToString());
72
73 throw ex;
74
75 }
76 }
77
78 private static void foo_B()
79 {
80 try
81 {
82 foo1();
83 }
84 catch(Exception ex)
85 {
86 Console.WriteLine("=================foo_B throw");
87 Console.WriteLine(ex.ToString());
88
89 throw;
90 }
91 }
92
93 private static void foo_C()
94 {
95 try
96 {
97 foo1();
98 }
99 catch(Exception ex)
100 {
101 Console.WriteLine("=================foo_C throw new Exception(\"throw again by new\",ex)");
102 Console.WriteLine(ex.ToString());
103
104 throw new Exception("throw again by new",ex);
105 }
106 }
107 }
108 }
输出结果:
=================foo_A throw ex;
System.Exception: happend in foo
at ConsoleApplication18.Class1.foo() in e:\my documents\visual studio project
s\consoleapplication18\class1.cs:line 54
at ConsoleApplication18.Class1.foo1() in e:\my documents\visual studio projec
ts\consoleapplication18\class1.cs:line 59
at ConsoleApplication18.Class1.foo_A() in e:\my documents\visual studio proje
cts\consoleapplication18\class1.cs:line 66
=================Main
System.Exception: happend in foo
at ConsoleApplication18.Class1.foo_A() in e:\my documents\visual studio proje
cts\consoleapplication18\class1.cs:line 73
at ConsoleApplication18.Class1.Main(String[] args) in e:\my documents\visual
studio projects\consoleapplication18\class1.cs:line 18
=================foo_B throw
System.Exception: happend in foo
at ConsoleApplication18.Class1.foo() in e:\my documents\visual studio project
s\consoleapplication18\class1.cs:line 54
at ConsoleApplication18.Class1.foo1() in e:\my documents\visual studio projec
ts\consoleapplication18\class1.cs:line 59
at ConsoleApplication18.Class1.foo_B() in e:\my documents\visual studio proje
cts\consoleapplication18\class1.cs:line 82
=================Main
System.Exception: happend in foo
at ConsoleApplication18.Class1.foo() in e:\my documents\visual studio project
s\consoleapplication18\class1.cs:line 54
at ConsoleApplication18.Class1.foo1() in e:\my documents\visual studio projec
ts\consoleapplication18\class1.cs:line 59
at ConsoleApplication18.Class1.foo_B() in e:\my documents\visual studio proje
cts\consoleapplication18\class1.cs:line 89
at ConsoleApplication18.Class1.Main(String[] args) in e:\my documents\visual
studio projects\consoleapplication18\class1.cs:line 29
=================foo_C throw new Exception("throw again by new",ex)
System.Exception: happend in foo
at ConsoleApplication18.Class1.foo() in e:\my documents\visual studio project
s\consoleapplication18\class1.cs:line 54
at ConsoleApplication18.Class1.foo1() in e:\my documents\visual studio projec
ts\consoleapplication18\class1.cs:line 59
at ConsoleApplication18.Class1.foo_C() in e:\my documents\visual studio proje
cts\consoleapplication18\class1.cs:line 97
=================Main
System.Exception: throw again by new ---> System.Exception: happend in foo
at ConsoleApplication18.Class1.foo() in e:\my documents\visual studio project
s\consoleapplication18\class1.cs:line 54
at ConsoleApplication18.Class1.foo1() in e:\my documents\visual studio projec
ts\consoleapplication18\class1.cs:line 59
at ConsoleApplication18.Class1.foo_C() in e:\my documents\visual studio proje
cts\consoleapplication18\class1.cs:line 97
--- End of inner exception stack trace ---
at ConsoleApplication18.Class1.foo_C() in e:\my documents\visual studio proje
cts\consoleapplication18\class1.cs:line 104
at ConsoleApplication18.Class1.Main(String[] args) in e:\my documents\visual
studio projects\consoleapplication18\class1.cs:line 40