Try-Catch无法正确定位异常位置,我推荐2个有效技巧
宇宙第一开发IDE Visual Studio的调试功能非常强大,平常工作debug帮助我们解决不少问题。今天分享两个异常捕获的技巧,希望能够帮助解决一些问题。
以下两种情况,我相信大家都会遇到过。
- 1.没有使用Try-Catch语句,当异常发生的时候,能够自动跳转到异常发生的地方,在使用Try-Catch捕获异常的时候,直接跳转到Catch语句的位置,并不会自动定位到异常代码的位置。
- 2.使用Try-Catch的时候,多层方法调用时,并不能直接查看到异常代码的位置。
技巧1:自动定位到异常代码位置
针对问题1,我们最想要的结果是,哪里有代码出现错误了,就直接定位到哪儿,异常出在哪行代码上,我一眼就能看得出,这样就能更快地处理问题了。
对于问题1,所出现的这种情况,简单复现一下一个空引用的异常
namespace ExceptionSample
{
class Program
{
static void Main(string[] args)
{
try
{
Random random = null;
Console.WriteLine(random.Next());
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadLine();
}
}
}
上面的异常代码NullReferrenceException,Debug模式下,会跳转到catch语句这里。你可能觉得这挺简单的......可实际实际工作中,你的一个方法中仅仅只这一个对象吗?
在实际工作中可能不止random一个对象,代码复杂,对象够多,几十个也有,我们就很难定位到异常出错的代码了。StackTrace可以定位到那个函数调用错了,并不能定位到哪一行代码出错了。
为了解决这个行为可以通过在Visual Studio中菜单栏中的调试》窗口》异常设置中去配置。如下图所示:
勾选上Common Language Runtime Exceptions下列的异常单选框。有点多,以前的设置有些变化。
现在我们再看之前的代码,使用Try-Catch语句捕获异常的时候,就会直接定位到异常代码的位置了,如下图示:
static void Main(string[] args)
{
try
{
Random random = null;
Random random1 = new Random();
Random random2 = new Random();
Random random3 = new Random();
Console.WriteLine(random1.Next());
Console.WriteLine(random2.Next());
Console.WriteLine(random3.Next());
Console.WriteLine(random.Next());
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadLine();
}
技巧2:正常的throw 姿势
还是之前的一个方法,我已经将异常设置回复默认了。
static void Main(string[] args)
{
try
{
Random random = null;
Console.WriteLine(random.Next());
}
catch (Exception ex)
{
System.Diagnostics.Debug.Write(ex);
throw ex;
}
}
我们再输出中可以看到(ps:项目名称用的之前的,不介意哈)
错误的代码在16行。可实际工作中的情况并不是这样简单,基本上是A方法调用B方法,B方法调用C方法,代码如下所示:
在Main方法中调用ThrowNullReferrence(),方法ThrowNullReferrence中调用SetNullReferrence()。代码变复杂后,一层嵌套一层。这个时候能正确显示出代码异常的位置吗?
static void Main(string[] args)
{
try
{
ThrowNullReferrence();
}
catch (Exception ex)
{
System.Diagnostics.Debug.Write(ex);
throw ex;
}
}
public static void ThrowNullReferrence()
{
try
{
SetNullReferrence();
}
catch (Exception ex)
{
System.Diagnostics.Debug.Write(ex);
throw ex;
}
}
public static void SetNullReferrence()
{
try {
Random random = null;
Console.WriteLine(random.Next());
}
catch(Exception ex)
{
System.Diagnostics.Debug.Write(ex);
throw ex;
}
}
我们可以通过下图看到:
System.NullReferenceException: 未将对象引用设置到对象的实例。
在 ExceptionSample.Program.SetNullReferrence() 位置 D:\Learn\延迟加载\LinqLayzLoad\LinqLayzLoad\Program.cs:行号 39System.NullReferenceException: 未将对象引用设置到对象的实例。
在 ExceptionSample.Program.SetNullReferrence() 位置 D:\Learn\延迟加载\LinqLayzLoad\LinqLayzLoad\Program.cs:行号 44
在 ExceptionSample.Program.ThrowNullReferrence() 位置 D:\Learn\延迟加载\LinqLayzLoad\LinqLayzLoad\Program.cs:行号 27System.NullReferenceException: 未将对象引用设置到对象的实例。
在 ExceptionSample.Program.ThrowNullReferrence() 位置 D:\Learn\延迟加载\LinqLayzLoad\LinqLayzLoad\Program.cs:行号 32
在 ExceptionSample.Program.Main(String[] args) 位置 D:\Learn\延迟加载\LinqLayzLoad\LinqLayzLoad\Program.cs:行号 15
错误代码的位置在39行,以上出现异常的地方都是throw的位置。
原因呢?
catch捕获完后,如果要向上抛出,应该重新实例化一个新的异常对象,再向上抛出,这个最外层方法catch到的才是完整的异常,当然也包括完整的堆栈信息,这样才能定位到异常代码的位置。
要使用 throw new Exception
改造后的例子如图,精准定位到
39行的空引用异常
Console.WriteLine(random.Next());
结语
分享之前看到的一个老程序员的经验之谈:“多coding,少debug”
Try-Catch无法正确定位异常位置,我推荐2个有效技巧的更多相关文章
- WinDBG快速定位异常位置
在WinDBG中通过搜索内存中保存的CONTEXT结构来定位发生的异常信息,再通过WinDBG命令.cxr显示对应的调用堆栈信息. .foreach ( place { s-[1]d 0 L?FF ...
- springmvc请求参数异常统一处理,结合钉钉报告信息定位bug位置
参考之前一篇博客:springmvc请求参数异常统一处理 1.ExceptionHandlerController package com.oy.controller; import java.tex ...
- JUnit 4 如何正确测试异常
本篇讲述如何在 JUnit 4 下正确测试异常,我会从 try..catch 的方式谈起,然后说到 @Test(expected=Exception.class), 最后论及 @Rules publi ...
- .net程序调试一:快速定位异常
作为一个程序员,解BUG是我们工作中常做的工作,甚至可以说解决问题能力是一个人工作能力的重要体现.因为这体现了一个程序员的技术水平.技术深度.经验等等. 那么在我们解决BUG的过程中,定位问题是非常重 ...
- .NET程序调试技巧(一):快速定位异常的一些方法
作为一个程序员,解BUG是我们工作中常做的工作,甚至可以说解决问题能力是一个人工作能力的重要体现.因为这体现了一个程序员的技术水平.技术深度.经验等等. 那么在我们解决BUG的过程中,定位问题是非常重 ...
- TextArea中定位光标位置
原文:TextArea中定位光标位置 在项目中,遇到一个场景:希望能在TextArea中输入某条记录中的明细(明细较简单,没有附属信息,只用记录顺序和值即可,譬如用"+"号来作为明 ...
- oops_根据epc定位linux_kernel_panic位置
韩大卫@吉林师范大学 2014.12.10 转载请表明出处 ***************************************************** 关于内核报错 “Unable t ...
- C#Exception 追踪异常位置
1:在编写软件时,保护关键位置的代码正常运行,要对这位置进行异常处理try catch private void StartTCPServer() { try { ........//我们要确保知道这 ...
- hp小机定位网卡位置
rad已经被olrad取代 HPUX下定位网卡位置 一台HP小型机,可能配了多块网卡,在系统中以la ...
随机推荐
- java下载和环境变量配置
初学java,以前没有接触过这方面内容,所以简要记录一下我2个月的学习流程. 首先,我在慕课上学习java的基础,浙江大学翁恺老师的课程. 下载ECLIPSE-java 进入官网:https://ww ...
- AcWing 906. 区间分组
//1.将所有区间按左端点从小到大排序 //2.从前往后处理每个区间,判断能否将其放到某个现有的组中 //判断某一组的最后一个区间的右端点是否小于该区间的左端点 //如果大于或等于,就开新组,如果小于 ...
- 题解 【Codeforces381A】 Sereja and Dima
本题是很好的双指针练习题. 关于双指针,详见洛谷日报#73. 我们可以用两个指针l和r表示题中两人接下来要比较的数字,用fl标记下一个将要取的人,并分别用两个计数器统计双方的答案. 因此,我们有了如下 ...
- Strategic game树形DP解法(Poj1463,Uva1292)
已经写过本题用二分图的做法,见这儿. 本题的图是一棵树,求最小点覆盖也可以用树形DP的做法. 定义状态f[0/1][u]表示以u为根的子树,u选取/不选最少需要选取多少点来覆盖. 显然 f[0][u] ...
- 牛客腾讯2020校园招聘-后台&综合-第一次笔试
第一题 Q: 小Q想要给他的朋友发送一个神秘字符串,但是他发现字符串的过于长了,于是小Q发明了一种压缩算法对字符串中重复的部分进行了压缩,对于字符串中连续的m个相同字符串S将会压缩为m|S,例如字符串 ...
- html中的路径详解
路径指文件存放的位置,在网页中利用路径可以引用文件,插入图像.视频等.表示路径的方法有两种:相对路径,绝对路径.以下讨论均是在HTML环境下进行. 相对路径 相对路径是指目标相对于当前文件的路径,网页 ...
- thinkphp的模型操作
先开个坑 WHERE篇 1, 模糊查询 where['keyword'] = [ 'like' , '%test%'] 2, 不等于,大于 ,小于 EQ 等于(=)NEQ 不等于(<& ...
- php对字符串的操作
php最文字的处理很是强大,之前一直云里雾里,这次学习一下. 1,' 与 ”的区别 <?php //双引号中的特殊字符会被解析 echo "你好\t我好";echo &quo ...
- python的类定义与实例化
理解类属性和实例属性: 直接在类里面定义的变量叫类属性,类属性是公有的,每个类实例化就自动拥有类的属性,且实例化对象的这个属性的初始地址指向类属性的地址 如果直接给实例化对象的属性赋值这样会改变该属性 ...
- IntelliJ IDEA 2017.3尚硅谷-----查看项目配置