非原创,转载自:  

http://www.cnblogs.com/killmyday/archive/2010/09/05/1818533.html

.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);
    }
}

.NET 4.0里异常处理的新机制的更多相关文章

  1. Swift2.0-异常处理(Exception handler)

    Swift2.0-异常处理(Exception handler) 前言 关于我们为什么要使用异常处理,请看百度百科为我们作出的描述,想要更详细的资料请点这里 异常处理,英文名为exceptional ...

  2. 在ASP.NET2.0里打印网页指定的内容(比如打印网页里的一个Table)

    原文:在ASP.NET2.0里打印网页指定的内容(比如打印网页里的一个Table) 打印指定内容: <html> <head> <script   type= " ...

  3. Asp.net2.0里的SessionPageStatePersister

    备注: ASP.NET 页可在处理和提供任何网页所必需的原本无状态 HTTP 请求与响应之间存储 Page 状态信息.此状态称为“视图状态”. ASP.NET 的默认持久性机制是使用 HiddenFi ...

  4. asp.net 2.0里也可以用JSON的使用方法

    本人找到一份,可以在asp.net2.0里实现JSON方式传送数据的方法.但是原方法,不能在数据中带有{.}.[.]."等,所以我做特意做了转意. 全部代码如下. /// <summa ...

  5. Mac OS X 10.10.5 中 VirtualBox 5.0 里的 Win7 虚拟机无法使用 USB 3.0 设备的解决办法(补充说明)

    上一篇文章中,我说到了如何在Mac OS X 10.10.5 中让 VirtualBox 5.0 里的 Win7 虚拟机使用 USB 3.0.最近碰巧升级 MacBook Pro 为最新的 15 吋 ...

  6. Android openGL ES 2.0里Surfaceview背景透明

    surfaceview的黑色背景会挡住其父的背景,现在把surfaceview的背景设为透明,既可以看到所绘的3D物体,又可以看到背景. 在onSurfaceCreated里,调用GLES20.glC ...

  7. 【Python 20】BMR计算器4.0(异常处理)

    1.案例描述 基础代谢率(BMR):我们安静状态下(通常为静卧状态)消耗的最低热量,人的其他活动都建立在这个基础上. 计算公式: BMR(男) = (13.7*体重kg)+(5.0*身高cm)-(6. ...

  8. yii2.0里的redirect跳转方法

    在yii2框架里难免会出现跨控制器跳转,调用方法等,这就用到了redirect了, 带参数的 $control=Yii::app()->runController('site/show/id/2 ...

  9. vc6.0里使用lib(静态库)的方法

    vc6.0 中使用lib文件 使用库的方法如下:1. 包含库的头文件(把库的头文件包含到项目中)在应用程序工程中使用#include "file path"file path可以为 ...

随机推荐

  1. python读取bin文件并下发串口

    # coding:utf-8import time, serialfrom struct import *import binascii file = open('E:\\1.bin', 'rb')i ...

  2. (转载)CSS中zoom:1的作用

    CSS中zoom:1的作用兼容IE6.IE7.IE8浏览器,经常会遇到一些问题,可以使用zoom:1来解决,有如下作用:触发IE浏览器的haslayout解决ie下的浮动,margin重叠等一些问题. ...

  3. thinkPHP框架学习笔记

    class ZhuantiAction extends Action { public function index() { $name = trim($this->_get('name')); ...

  4. 背包问题matlab程序

    clearclca=0.95k=[5;10;13;4;3;11;13;10;8;16;7;4];k=-k;d=[2;5;18;3;2;5;10;4;11;7;14;6];restriction=46; ...

  5. MyBatis 批量修改记录

    <insert id="update" parameterType="java.util.List"> UPDATE setting SET con ...

  6. drupal7 上传文件中文乱码

    drupal7自带有file模块,可以上传文件. 但是存在问题:如果上传的文件名称是中文,存储在文件下面的文件名称是乱码的,解决办法如下:参考出处 includes/file.inc中,修改两处代码, ...

  7. JavaScript 操作符 变量

    一.操作符: 一元操作符 递增操作符 递减操作符 分为 前置型(--a    ++a) 和 后置型 (a--    a++) 区别如下: var a = 3,b=6; c = --a +b; //c= ...

  8. 如何用脚本快速修改IP地址(Netsh)

    如何用脚本快速修改IP地址(Netsh) 如果通过Windows的网络属性修改Ip/网关,真是太麻烦了.最近一个项目经常要切换ip,所以我写了两个脚本:c:\116.bat netsh interfa ...

  9. websphere安装验证报错 忘记密码的配置

    http://blog.csdn.net/yulimin/article/details/4048897 ADMU7704E: 在尝试启动与服务器相关联的 Windows 服务时失败:server1: ...

  10. HDU 3416 Marriage Match IV

    最短路+最大流 #include<cstdio> #include<cstring> #include<string> #include<cmath> ...