大尾巴狼

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

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


在我们定位异常发生位置的时候,一般都能得到正确的异常信息(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 大尾巴狼 阅读(1712) 评论(8)  编辑 收藏 网摘 所属分类: dotNet技术和知识

评论

#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      

学习了   回复  引用  查看    




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 801354




相关文章:

相关链接:
<2007年6月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

公告

点击这里给我发消息
Locations of visitors to this page
对于业务实体有没有一个较好的解决方案啊

与我联系

搜索

 

常用链接

留言簿

我参与的团队

随笔分类(46)

随笔档案(37)

文章分类(9)

文章档案(9)

收藏夹(14)

coworker

开源项目

值得一看

最新随笔

积分与排名

最新评论

阅读排行榜