C++.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