Welcome

首页 / 软件开发 / .NET编程技术 / .NET 4.0新特性 - Corrupted State Exceptions

.NET 4.0新特性 - Corrupted State Exceptions2010-12-29 博客园 Sean Zhu作为程序员,我想很多人应该都有过跟异常打交道的经历。而且相信也有很多人也都写过catch(Exception e){//blabla}这种把所有未知异常一股脑儿捕获并处理掉的代码吧。不管是为敷衍客户也好,让程序继续运行以避免糟糕的用户体验也罢,在微软眼中,这种处理方式都是不对滴,特别是当你的程序是作为一个插件寄存在别的程序如VS,Offcie中时,这种情况下对有些严重的异常如访问冲突我们更应当是让程序结束而不是继续运行。然而很多时候,我们并不清楚哪些异常是严重的,哪些是可以让程序继续运行的,因为在.NET 4.0以前,CLR会很忠实的把所有大大小小的异常一股脑儿的都抛给程序员处理。不过这个问题在4.0以后会得到很好的解决了。因为对有些严重的会引起进程崩溃的异常的处理以后会由CLR来统一处理而不再交给我们可怜的程序员了。下面我将对这种异样处理做一些简单的介绍。

为什么需要Corrupted State Exceptions

异常有大有小,小的如字符串为空,这些一般是用户输入问题,它不会引起整个程序或者系统中相关进程出现崩溃的情况;大的如访问冲突异常,这可能是你的程序在做一些可能会引起操作系统崩溃的事情,这种异常一般都比较严重,一般如果出现这种异常,通常程序应该做的是结束当前进程,然后老老实实向用户报告你犯傻了并提示他重启程序。不过在.NET 4.0以前,CLR是很相信程序员不会搞出一些诸如catch(Exception e){return;}这种不负责任的代码的,因此它不分轻重缓急,只要是异常,它统统都会抛出来,这里面不仅仅有托管代码的异常,也有一些.NET程序员不太好看懂的COM和WIN32异常。CLR相信程序员在捕获异常的时候会只处理他们清楚的异常,但很多时候,作为开发人员,由于上面有老板,下面有客户,我们真的很难做人,想想如果老板动不动就听又客户抱怨他们只不过点了两下按钮程序就报错然后结束了,他还能给你加薪么?虽然很多时候我们清楚我们的代码不会出问题,但我们很难保证天时地利人和样样俱全,为了给老板和客户一个交代,这时候很多人都会选择去捕获所有的异常,然后记录下异常信息,然后程序继续彪悍的跑下去。

看似一些都很完美,客户不会再像以前那么频繁的抱怨程序down掉,老板也就高兴了。但有人不高兴。小的未知异常当然不会捅大的篓子,但对有些可能导致程序甚至操作系统崩溃的异常如果不中断程序的话可能影响的就是一大片了。这个时候客户可能不会抱怨你,但他会抱怨微软出了个烂操作系统,一天到晚蓝屏,或者他会抱怨微软的Office或者IE太烂,他只不过加载了一个插件,结果整个Outlook就报错崩掉了。你是省事了,但微软得来被黑锅,而且他还不知道这个黑锅里面到底是咋回事。

当然上面是玩笑,不过不管怎样,从程序安全和稳定的角度来看catch(Exception e)确实不是一个好的编程习惯,然而木已成舟,既然无法避免程序员偷懒,微软只能采取一些补救措施了,这就是CLR新的异常处理机制的作用。

CLR怎么处理Corrupted State Exception

自4.0以后,CLR不会主动给你抛出所有异常了,对于那些它认为是危险的,可能导致进程崩溃的异常它会标记为Corrupted StateException并自己处理掉而不是抛给程序员来做,如AccessViolationException这种继承自 SystemException的异常就会被当做Corrupted StateException来处理。不过这里要注意的是,仅仅异常类型是可能会危险级别的异常还不够,CLR还会判断抛出异常的所有者,如果它发现是由操作系统抛出的访问冲突则会认为这是状态崩溃异常,但如果异常是由用户代码抛出,则CLR不会对其做特殊处理,它仍然会像以前一样将其正常抛出。

下面我们给出具体例子来演示.NET 4.0中CLR处理Corrupted State Exception的情况。

首先,我们想办法制造一个这种严重的异常,然后使用try,catch来看CLR是如何处理这段代码的。

01 unsafe static void T2()
02 {
03 try
04 {
05 int* pd = stackalloc int[1];
06 pd[1911] = 2;
07 Console.WriteLine(pd[1111]);
08 }
09 catch (Exception e)
10 {
11 Console.WriteLine(e.ToString());
12 }
13 }

在这段代码中,即使用户代码捕获所有通用异常,程序仍然会终止并抛出AccessViolationException异常信息,这是因为 AccessViolationException是Corrupted State异常,并且它是由系统抛出。所以这里CLR不会把这个异常交给用户处理,而是主动报告错误,中断进程,然后退出程序。

我们再看另外一段代码:

01 static void T3()
02 {
03 try
04 {
05 throw new System.AccessViolationException();
06 }
07 catch (Exception e)
08 {
09 Console.WriteLine(e.ToString());
10 }
11 }