大尾巴狼

所谓大尾巴狼,就是装腔作势。

为什么有时不能正确定位到异常的发生位置?


在我们定位异常发生位置的时候,一般都能得到正确的异常信息(Exception.Message)。
但是当根据调用堆栈来定位异常发生点的时候,却往往得不到正确的位置,即正确的调用堆栈。
这与再次抛出异常的方式有关,请看下面的程序和输出结果。

在foo_ABC中捕获、处理、并重新抛出异常。在Main函数中最终来处理异常,获得详细的异常信息。
当使用 throw ex 后,在异常的调用堆栈里就不是正确正确的异常发生位置。
如果有源代码则可以顺着继续找,如果没有的话,则不好正确定位异常的发起的根源。

结论:
异常的调用堆栈,是以发生异常或者throw ex为起点的,当使用throw ex时会覆盖掉发生异常时产生的调用堆栈。
所以, foo_A()函数里抛出异常的方式要慎用!


  1 using System;
  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


 





 

posted on 2007-06-30 14:26 大尾巴狼 阅读(1769) 评论(8) 编辑 收藏

评论

#1楼 2007-06-30 15:47 Anders Cui      

嗯,该用throw;取代throw ex;  回复 引用 查看   

#2楼 2007-06-30 18:20 li-new[未注册用户]

在release的时候是得不到这些详细的信息的。  回复 引用   

#3楼 2007-06-30 19:18 Ariel Y.      

@li-new
能否得到这些信息,不是由Release还是Debug决定的。
而是看同目录下是否有对应的pdb文件。

一般Release模式看不到调试信息是因为VS里边默认在Release模式下不输出pdb文件,这个在工程属性里可以设置。

具体位置是Build,然后选择编译模式,然后Advanced/Debug Info
 回复 引用 查看   

#4楼[楼主] 2007-06-30 23:02 大尾巴狼      

throw的问题,不知道是bug还是有意这样设计的??
既然存在肯定有他的原因,不知道什么时候适用throw ex的方式。
请高人指教啊!
 回复 引用 查看   

#5楼 2007-06-30 23:39 Cat Chen      

这个问题很多人都讨论过,要么用throw;,直接继续传递原来的异常;要么用throw new Exception(ex);,也就是用新的异常嵌套原来的。上述两种情况都能正常识别。

至于throw ex;,这被认为ex已经成功截获,然后再被截获的位置重新开始throw,这时候异常就不能被准确定位了。
 回复 引用 查看   

#6楼 2007-07-01 12:38 no words[未注册用户]

我倒!这么简单的问题居然还放在首页讨论,居然还有人说是bug?这种问题你不清楚你就不能叫.net程序员!异常处理是对一个程序员基本的要求!  回复 引用   

#7楼[楼主] 2007-07-03 07:54 大尾巴狼      

@no words
谢谢指教!
 回复 引用 查看   

#8楼 2007-07-30 10:03 Clark Zheng      

学习了  回复 引用 查看   

<2007年6月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

公告

点击这里给我发消息
Locations of visitors to this page
昵称:大尾巴狼
园龄:7年9个月
粉丝:1
关注:0

搜索

 
 

常用链接

最新随笔

随笔分类(46)

随笔档案(38)

文章分类(9)

文章档案(9)

coworker

开源项目

值得一看

积分与排名

最新评论

阅读排行榜

推荐排行榜