.NET 4.0里死处理的新机制

面前几乎上,有一个爱人咨询我怎么当.NET里无可知捕捉(catch)到部分充分了,而且以调试器里呢捕捉不顶。研究了一晃,是.NET
4.0里新的老处理机制捣的蹩脚。

 

每当.NET 4.0过后,CLR将会晤区分出有些颇(都是SEH异常),将这些老标识为破坏性异常(Corrupted
State Exception)。针对这些大,CLR的catch块不见面捕捉这些酷,即使你用类似下面的代码:

            try
            {
                TestMethod();
            }
            catch (Exception e)
            {
                Console.WriteLine(“Catching exception: {0}”, e);
            }

啊没有主意捕捉到这些特别。之所以要如此设计,在MSDN的文章Handling Corrupted State
Exceptions里既关系了。即,有一些支撑插件的次第,例如Visual
Studio或者SQL Server,它们支持调用托管代码编写成的插件,但是它自己自产生不少代码是由于非托管的C++写成的。由于插件经常会调用到非托管的API,而多时间,这些插件的代码根本不怕非知情哪处理非托管的API抛出来的SEH异常。在4.0在先,因为SEH异常被撤换成为了和普通.NET异常相同的怪,这样程序员只要用catch
( Exception e)的模式就是可以捕捉到有的死。这样处理的问题是,由于SEH异常通常都非是托管代码抛出的,托管代码根本不怕无晓得SEH异常被扔出去的由来,简单的catch (
Exception e)处理使得整个程序会处在一个异常不平静的状态,使得前为忽略的题材在背后以重重的计面世
— 例如保存于坏之多少。这样,看起使用catch
( Exception e)处理所有的充分的不二法门十分粗略,但其实让程序员或者用户以题材延后发生常,分析起来要花费还多的肥力。

 

据此当4.0随后,大部分SEH(我怀疑是有)异常且叫标识成破坏性异常,在.NET里,默认情况下CLR不见面捕捉它们,而是任由操作系统来处理—即关闭程序,并开拓一个不当对话框通知用户。为了保兼容性,在4.0以前编译的次第,例如当2.0、3.0与3.5编译的程序,依然采取的凡老的方针—即.NET会同时捕捉.NET异常和SEH异常。而在4.0脚编译的主次才会以初的国策,这吗是当篇章的开端,我之心上人所碰到的问题。你可于.NET
4.0脚编译下面的顺序,体验一下夫新变化:

Program.cs:

using System;
   using System.Runtime.InteropServices;
  
   namespace ConsoleApplication1
 {
     class Program
     {
         [DllImport("Ref.dll")]
         private extern static void TestMethod();
  
         static void Main(string[] args)
         {
             try
             {
                 TestMethod();
             }
             catch (Exception e)
             {
                 Console.WriteLine("Catching exception: {0}", e);
             }
         }
     }
 }

 

 

Ref.cpp:

#include "stdafx.h"
  
   extern "C" __declspec(dllexport) void TestMethod()
 {
          int *p = NULL;
          
          // 会导致.NET抛出一个AccessViolation异常
          *p = 10;
 }

 

点的代码里,Program.cs使用P/Invoke技术调用了Ref.dll文件里的TestMethod,但是TestMethod尝试被一个空指针赋值,导致一个AccessViolation异常。如果你当2.0底编译program.cs,并尽的话,这个AccessViolation异常会为catch(Exception e)捕捉到,而只要你于4.0下面编译并推行的话,你晤面发现catch
(Exception e)是无克捕捉到者那个的。

 

然并无是有着人且想只要之新的大机制,如果你的程序是于4.0脚编译并运行,而你而且想当.NET程序里捕捉到SEH异常的语,有少数单方案得以品味:

1.         在托管程序的.config文件里,启用legacyCorruptedStateExceptionsPolicy这个特性,即简化的.config文件类下面的文书:

 

App.config:

<?xml version="1.0"?>
<configuration>
 <startup>
   <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
 </startup>
    <runtime>
      <legacyCorruptedStateExceptionsPolicy enabled="true" />
    </runtime>
</configuration>

 

本条装置告诉CLR 4.0,整个.NET程序都使运用老的特别捕捉机制。

 

2.         在得捕捉破坏性异常的函数外面加一个HandleProcessCorruptedStateExceptions属性,这个特性只控制一个函数,对托管程序的另外函数没有影响,例如:

[HandleProcessCorruptedStateExceptions]
   static void Main(string[] args)
 {
     try
     {
         TestMethod();
     }
     catch (Exception e)
     {
         Console.WriteLine("Catching exception: {0}", e);
     }
 }

 

公也可下载示例代码自己尝试一下(需要VS
2010才会编译):

/Files/killmyday/CSEsample.zip

相关文章