c# 异常精准定位
在日常项目开发中,异常抛出和捕获是再平常不过的事情。通过try-catch我们可以方便的捕获异常,同时通过查看异常堆栈我们能发现抛出异常代码的位置。
例如下面这段代码:
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; namespace ExamplesProject
{
class Program
{
static int m = ;
static void Main(string[] args)
{
try
{
int a = , b = ;
Console.WriteLine(a / b);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
} Console.ReadLine();
}
}
}
这段代码非常简单,运行后他抛出了如下异常:
System.DivideByZeroException: Attempted to divide by zero.
at ExamplesProject.Program.Main(String[] args) in D:\Projects\ExamplesProject\ExamplesProject\Program.cs:line
没有问题,堆栈信息明确指出了抛出异常的位置,也正是除零异常发生的位置。
假如因为种种原因,需要把main方法的代码逻辑抽取到另外的方法里,像下面这样:
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; namespace ExamplesProject
{
class Program
{
static int m = ;
static void Main(string[] args)
{
try
{
Divide();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
} Console.ReadLine();
} public static void Divide()
{
try
{
int a = , b = ;
Console.WriteLine(a / b);
}
catch (Exception ex)
{
throw ex;
}
}
}
}
这段代码乍一看,好像也没有什么问题,divide的方法自己捕获并重新抛出了异常。
再来看一下异常信息:
System.DivideByZeroException: Attempted to divide by zero.
at ExamplesProject.Program.Divide() in D:\Projects\ExamplesProject\ExamplesProject\Program.cs:line
at ExamplesProject.Program.Main(String[] args) in D:\Projects\ExamplesProject\ExamplesProject\Program.cs:line
异常堆栈显示,抛出异常的方法是Divide(),异常代码位置是34行。可这里并不是异常真正的发生位置,真正的异常位置是第30行。
发生了什么??为什么不是第30行。
再来看一个例子。
假如业务变复杂了,代码又嵌套了一层。调用关系变复杂了,main()->divide()->divide1()。
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; namespace ExamplesProject
{
class Program
{
static int m = ;
static void Main(string[] args)
{
try
{
Divide();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
} Console.ReadLine();
} public static void Divide()
{
try
{
Divide1();
}
catch (Exception ex)
{
throw ex;
}
} public static void Divide1()
{
try
{
int a = , b = ;
Console.WriteLine(a / b);
}
catch (Exception ex)
{
throw ex;
}
}
}
}
运行代码,抛出如下异常:
System.DivideByZeroException: Attempted to divide by zero.
at ExamplesProject.Program.Divide() in D:\Projects\ExamplesProject\ExamplesProject\Program.cs:line
at ExamplesProject.Program.Main(String[] args) in D:\Projects\ExamplesProject\ExamplesProject\Program.cs:line
为什么异常位置是33行,而不是42行呢。代码嵌套的越深,错误隐藏的越深。如果是在大型系统中,将很难发现错误的真正位置。
作者就犯过这样的错误啊。问题到底在哪里呢?
问题的根源是,以上代码抛出的异常并没有体现层次关系,或者说异常的嵌套关系。理论上讲,divide1()方法中catch捕获到的异常为最内层异常,catch捕获后处理完,如果要向上层抛出,应该重新实例化一个新的异常对象,并将当前异常作为其innerException, 再向上抛出。以此类推,divide()方法捕获处理后如果要抛出异常也应该这样做。这样最外层的main方法catch到的异常才是完整的异常,自然包含完整的堆栈信息,错误定位就是精准的。
改造后的例子:
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; namespace ExamplesProject
{
class Program
{
static int m = ;
static void Main(string[] args)
{
try
{
Divide();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
} Console.ReadLine();
} public static void Divide()
{
try
{
Divide1();
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
} public static void Divide1()
{
try
{
int a = , b = ;
Console.WriteLine(a / b);
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
}
}
运行后,抛出如下异常:
System.Exception: Attempted to divide by zero. ---> System.Exception: Attempted to divide by zero. ---> System.DivideByZeroException: Attempted to divide by zero.
at ExamplesProject.Program.Divide1() in D:\Projects\ExamplesProject\ExamplesProject\Program.cs:line
--- End of inner exception stack trace ---
at ExamplesProject.Program.Divide1() in D:\Projects\ExamplesProject\ExamplesProject\Program.cs:line
at ExamplesProject.Program.Divide() in D:\Projects\ExamplesProject\ExamplesProject\Program.cs:line
--- End of inner exception stack trace ---
at ExamplesProject.Program.Divide() in D:\Projects\ExamplesProject\ExamplesProject\Program.cs:line
at ExamplesProject.Program.Main(String[] args) in D:\Projects\ExamplesProject\ExamplesProject\Program.cs:line
这一次,异常堆栈精准的定位了异常代码行第42行。
总结,以上例子非常简单,可是在实际开发中,我们总是会不经意忽略一些细节,最终导致上了生产后异常格外的难以追踪。
c# 异常精准定位的更多相关文章
- postgresql异常快速定位
今天下午在使用.NET链接postgresql的时候报了“3D000”的错误,经过测试得知原来是web.config中的数据库配置问题. 在这里有个小情况需要注意,postgresql是不允许创建相同 ...
- 如何实现室内Wi-Fi无线终端的精准定位
如何实现室内Wi-Fi无线终端的精准定位 如何实现室内Wi-Fi无线终端的精准定位 随着商圈020的兴起,室内定位技术的也如百花争艳般不断涌现.但随着室内Wi-Fi网的架设普及,基于Wi-Fi定位技术 ...
- vue开发东京买菜,全栈项目,前端django,带手机GPS精准定位,带发票系统,带快递系统,带微信/支付宝/花呗/银行卡支付/带手机号一键登陆,等等
因为博客园不能发视频,所以,完整的视频,开发文档,源码,请向博主索取 完整视频+开发文档+源码,duanshuiLu.com下载 vue+django手机购物商城APP,带支付,带GPS精准定位用户, ...
- django开发东京买菜,全栈项目,前端vue,带手机GPS精准定位,带发票系统,带快递系统,带微信/支付宝/花呗/银行卡支付/带手机号一键登陆,等等
因为博客园不能发视频,所以,完整的视频,开发文档,源码,请向博主索取 完整视频+开发文档+源码,duanshuiLu.com下载 vue+django手机购物商城APP,带支付,带GPS精准定位用户, ...
- 利用 Traceview 精准定位启动时间测试的异常方法 (工具开源)
机智的防爬虫标识原创博客地址:http://www.cnblogs.com/alexkn/p/7095855.html博客求关注: http://www.cnblogs.com/alexkn 1.启动 ...
- Ceph RGW服务 使用s3 java sdk 分片文件上传API 报‘SignatureDoesNotMatch’ 异常的定位及规避方案
import java.io.File; import com.amazonaws.AmazonClientException; import com.amazonaws.auth.profile ...
- 大数据量冲击下Windows网卡异常分析定位
背景 mqtt的服务端ActiveMQ在windows上,多台PC机客户端不停地向MQ发送消息. 现象 观察MQ自己的日志data/activemq.log里显示,TCP链接皆异常断开.此时尝试从服务 ...
- web异常流量定位:iftop+tcpdump+wireshark
一个简单的运维小经验. 场景:web服务器出现异常流量,web集群内部交互出现大流量,需要定位具体的http请求,以便解决问题. 目的:找出产生大流量的具体http请求. 工具: ift ...
- 记录一次cefsharp1输入法在win7下异常解决定位
最近几天都被基于cefSharp封装的浏览器控件搞疯了!对于cefSharp基本满足当前所做项目的需求,但是有一个问题一直困扰我,那就是系统中偶尔会出现输入法不能转换到中文.而且这个问题似乎没有什么规 ...
随机推荐
- Docker中Nginx服务器相关配置
工作中经常需要在服务器上来做一下实验,亲自动手看看效果是否与理论描述的相同.用docker可以很方便的配置所需要的环境,以下内容记录了如何用docker配置一个nginx服务器 下载nginx 从默认 ...
- LeetCode刷题总结-树篇(下)
本文讲解有关树的习题中子树问题和新概念定义问题,也是有关树习题的最后一篇总结.前两篇请参考: LeetCode刷题总结-树篇(上) LeetCode刷题总结-树篇(中) 本文共收录9道题,7道中等题, ...
- ASP.NET CORE 使用Consul实现服务治理与健康检查(2)——源码篇
题外话 笔者有个习惯,就是在接触新的东西时,一定要先搞清楚新事物的基本概念和背景,对之有个相对全面的了解之后再开始进入实际的编码,这样做最主要的原因是尽量避免由于对新事物的认知误区导致更大的缺陷,Bu ...
- 6. abp中的拦截器
abp拦截器基本定义 拦截器接口定义: public interface IAbpInterceptor { void Intercept(IAbpMethodInvocation invocatio ...
- 不加班的秘诀:如何通过AOE快速集成NCNN?
作为我司头发储量前三的程序员 始终仗着头发多奋斗在加班的第一线 时时灵魂拷问自己 年轻人,你凭什么不加班? 虽然我没有女朋友但是,我有代码呀 但我不明白的是,隔壁工位那个,到岗比我迟,下班比我早,天天 ...
- zip,rar及linux下常用的压缩格式
日常操作中我们经常使用到文件压缩操作,其使用一些特定的算法来减小文件的大小,可以提高传输数据时的速率和减少数据在一些存储机制上占有的空间大小,实现空间利用最大化. 比如:如果你想通过邮箱发送一个文件夹 ...
- 代码管理平台之git
yum install -y gitmkdir -p /date/gitrootcd !$git init git add 1.txtgit commit -m "add 1.txt&quo ...
- PageRank算法小结
PageRank 这个学期选了数据挖掘的课程,期末要做一个关于链接分析算法的报告,这是PR算法的小结. 算法 PR算法基于等级权威的思想,及不仅考虑指向该网页的链接数,同时也考虑指向该网页网站的重要程 ...
- 自己封装Linux命令行万能解压命令
问题背景 Linux下经常需要解压文件,直接在命令行敲命令解压是最便捷的. 但问题在于,不同的压缩格式,需要用不同命令和不同参数,完全记不住啊. 解决方式 既然记不住,那就换一种思路,假如有一条命令能 ...
- Java 读取excel表格文件
注意,本文使用的Jar包为jxl.jar,只能处理97-03版本xls格式的Excel jar包 maven依赖: <dependency> <groupId>net.sour ...