我看到了一些关于Rotor(和CLR)中使用的异常处理机制的问题。下面是关于Rotor异常处理的另一个注意事项列表。目的是帮助Rotor开发人员调试和理解CLR中的异常。

异常生成和抛出

此步骤在很大程度上取决于异常的类型以及从何处引发异常:

jitted代码中的软件异常---使用C#中throw new MyException(…)引发的异常

  • 异常对象的创建方式与任何其他托管对象的创建方式相同
  • vm\jitiface.cpp中调用JIT_Throw
  • HelperFrame被推送以标记从jitted到EE代码的转换。这是可靠的stack walk工作所必需的——安全性和垃圾收集是可靠stackwalk的主要用户。
  • vm\excep.cpp中调用了RaiseTheException
  • 异常对象存储在当前线程对象中
  • EXCEPTION_COMPLUS异常是使用Win32的RaiseException API引发的

执行引擎代码中的软件异常---在clr\src\vm目录中使用COMPlusThrow(…)引发异常

  • 如果尚未提供给调用,则异常对象的创建方式与任何其他托管对象的创建方式相同
  • vm\excep.cpp:RaiseTheException被调用,故事的其余部分与第一个案例相同。
  • 注意:不需要推送任何转换框架
  • 注意:在托管异常堆栈跟踪中不包含C++ stacttrace。

jitted代码中的硬件异常-如访问空对象、除以零等。

  • 将调用jitted代码的异常处理程序。大多数时候它是vm\i386\excepx86.cpp:COMPlusFrameHandler。
  • 异常被标识为直接来自vm\i386\excepx86.cpp:CPFH_HandleManagedFault中的jitted代码。
  • 推送FaultingExceptionFrame以标记从jitted到EE代码的特殊转换。
  • 使用vm\i386\excepx86.cpp:LinkFrameAndRow和关联的asm帮助程序重新引发异常。
    对于Win32/i386 SEH,通过将IP修改为指向NakedThrowHelper的异常过滤器返回EXCEPTION_CONTINUE_EXECUTION来完成重新触发。
    对于PAL_PORTABLE_SEH,通过简单调用LaunchNakedThrowHelper来完成重新触发。
  • 第二次在异常过滤器中,为硬件异常创建正确类型的异常对象。硬件异常到BCL异常类型的映射在vm\excep.cpp:MapWin32FaultToCOMPlusException中完成。
  • 注意:硬件异常重试是一个实现细节,它应该允许可继续的异常(异常继续执行)无缝工作。CLI目前不支持可延续的异常,但将来可能会有所改变。此外,可能存在一些互操作场景,其中异常继续执行非常重要。
  • 注意:对于PAL_PORTABLE_SEH,硬件异常的重新触发是不同的,因为PAL不支持异常继续执行。稍后为调试器支持添加了异常继续执行。

执行引擎代码中的硬件异常

执行引擎代码中的硬件异常通常不应该发生。如果他们这样做了,通常意味着事情真的出了问题,需要大量的运气才能从这种情况中恢复过来。不过,这条规则有几个例外:

  • 写入屏障帮助程序(vm\i386\jithelp.asm:JIT_write barrier and friends)中的访问冲突被转换为调用程序中的访问冲突。转换在vm\i386\excepx86.cpp:CPFH_AdjustContextForWriteBarrier中完成。这允许JIT在调用写回载波时优化空检查。FJIT当前不使用此功能。
  • 尽管存在一些防止堆栈溢出异常(vm\stackprobe.h)的屏蔽,但它们可能发生在执行引擎代码中,这通常非常糟糕。这是为.NET v1设计的,CLR团队正在为Whidbey开发更好的解决方案。便携式堆栈溢出处理不在转子-我们只是死时堆栈溢出发生。可移植堆栈溢出处理的设计和实现留给读者练习
  • 元数据代码用于访问监视(#define ZAP_MONITOR),以允许按配置文件引导的元数据布局优化。检测是通过使所有元数据访问A/V、记录它们并通过异常继续执行从它们恢复来完成的。(是的,这个解决方案的性能很差。)元数据工具不是作为Rotor的一部分提供的,但是必须记住它以避免代码损坏。

FCalls中的软件异常--使用FCThrow(…)及其类似调用引发的异常

Fcall闻起来像jitted代码,但实际上不是,因此Fcall中的异常处理是特殊的。

  • 如果未推送helper框架,则使用FCThrow helpers从fcall抛出异常。(如果推送helperframe,则它是使用complushrow在执行引擎代码中抛出软件异常的简单方法)
  • FCThrow helper使用特殊帧ATTR_CAPTURE_DEPTH_2推动辅助帧。因此,只能直接从FCALL调用FCThrow。不能从从FCALL调用的函数调用它。
  • 一旦helper框架被推送,complushrow就会像执行引擎代码中的任何其他软件异常一样实际抛出异常。
  • 注意:FCThrow只是HELPER_METHOD_FRAME_BEGIN(…);complusthrow(…);HELPER_METHOD_FRAME_END()的快捷方式。如果您看到了长代码模式,那么在尝试使用FCThrow对其进行优化时要小心—它可能是有原因的。fcall依赖于一个非常脆弱的x86解释器。这个翻译有时需要帮助.

可以看到,所有异常都转换为一个看起来像常规托管异常的统一案例。从托管代码引发的每个异常(无论是硬件异常还是软件异常)都会下放到Win32 RaiseException层。这样做是为了保持一致性。它被认为可以简化互操作性的实现。

处理异常

异常的处理遵循两次机会的Win32模型。
第一次,stackwalker为堆栈上的每个方法调用回调。一旦某个过滤器返回它处理异常,异常展开的第二次传递就开始了。
第二次,堆栈已展开。展开代码的结构在本机Win32 i386异常处理和PAL可移植异常处理之间有所不同。

异常和垃圾收集器

请注意,对RaiseException的调用是由EE代码发出的,并且此代码以协作模式运行。因此,在异常分派期间不会阻止垃圾收集。

异常和帧

帧的链接列表(Frame-vm\frames.h类的后代)与每个线程对象关联。这些是可靠的堆栈遍历基础设施的关键部分。执行引擎代码正在使用一种特殊的机制来释放异常时的链。COMPLUS-TRY/COMPLUS-CATCH宏(vm\exceptmacros.h)通过在异常时调用unwind frame chain(vm\excepp.cpp)来展开帧链。此外,这些宏还释放嵌套的异常信息(vm\excep.cpp:UnwindExInfo)并还原GC模式,这非常方便。
请注意,UnwindFrameChain正在访问已展开的堆栈空间。这是可行的,但它取决于堆栈展开的微妙的低级实现细节。由于Win32/i386 SEH和PAL_PORTABLE_SEH之间堆栈展开的低级实现细节不同,因此COMPLUS_TRY/COMPLUS_CATCH宏对于这两个宏是不同的。它还解释了为什么有必要在执行引擎中使用COMPLUS-TRY/COMPLUS-catch捕获异常,而不使用常规的PAL-TRY/PAL-catch除外。
CLR开发人员没有选择通过为类框架创建C++析构函数来解开帧链,这将是一个非常简单的解决方案。这可能是一个纯粹的历史遗留物;它们可能有一些性能童话;或者对象析构函数与结构化异常处理的混合,而MSC不支持的结构异常处理会在编写代码时造成太多的不适。

异常与C++对象展开

在异常解除时,PAL_PORTABLE_SEH 不调用堆栈上的对象的C++析构函数。这是可以的,因为执行引擎代码似乎没有利用当前的C++特性。嗯,我们还没有找到它依赖于被调用的C++的地方。这可能会因Whidbey而改变

异常和安全

由于存在安全隐患,因此从异常处理中正确执行堆栈遍历非常重要。对于过滤器来说,这是特别棘手的,因为在调用过滤器时,真正的堆栈是不展开的。在抛出异常到最后调用异常之间,可以调用来自堆栈上源代码的任意用户代码。

Rotor

Rotor里的异常处理的更多相关文章

  1. [R]R语言里的异常处理与错误控制

    之前一直只是在写小程序脚本工具,几乎不会对异常和错误进行控制和处理. 随着脚本结构和逻辑更复杂,脚本输出结果的准确性验证困难,同时已发布脚本的维护也变得困难.所以也开始考虑引入异常处理和测试工具的事情 ...

  2. Visual C++ 里的异常处理

    微软Visual C++是Win32最广泛使用的编译器,因此Win32反向器对其内部工作非常熟悉.能够识别编译器生成的粘合代码有助于快速集中于程序员编写的实际代码.它还有助于恢复程序的高级结构.我将集 ...

  3. int main(int argc, char * argv[]) 里的异常处理

    #import <UIKit/UIKit.h> #import "AppDelegate.h" int main(int argc, char * argv[]) { ...

  4. java异常处理的设计

    有一句这样话:一个衡量Java设计师水平和开发团队纪律性的好方法就是读读他们应用程序里的异常处理代码. 本文主要讨论开发Java程序时,如何设计异常处理的代码,如何时抛异常,捕获到了怎么处理,而不是讲 ...

  5. Struts2、Spring MVC4 框架下的ajax统一异常处理

    本文算是struts2 异常处理3板斧.spring mvc4:异常处理 后续篇章,普通页面出错后可以跳到统一的错误处理页面,但是ajax就不行了,ajax的本意就是不让当前页面发生跳转,仅局部刷新, ...

  6. [转贴]从零开始学C++之异常(一):C语言错误处理方法、C++异常处理方法(throw, try, catch)简介

    一.C语言错误处理方法 1.返回值(if … else语句判断错误) 2.errno(linux 系统调用) 3.goto语句(函数内局部跳转) 4.setjmp.longjmp(Do not use ...

  7. 从零开始学C++之异常(一):C语言错误处理方法、C++异常处理方法(throw, try, catch)简介

    一.C语言错误处理方法 1.返回值(if … else语句判断错误) 2.errno(linux 系统调用) 3.goto语句(函数内局部跳转) 4.setjmp.longjmp(Do not use ...

  8. day 21 - 1 包,异常处理

    创建目录代码 1. 无论是 import 形式还是 from...import 形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法2. 包是目录级的(文 ...

  9. day21:包和异常处理

    1,复习 # 序列化模块 # json # dumps # loads # dump 和文件有关 # load load不能load多次 # pickle # 方法和json的一样 # dump和lo ...

随机推荐

  1. 【linux】linux修改文件句柄数量,linux文件句柄的修改分为用户级和系统级

    说明: liunx中文件句柄有两种,一种是用户级的,一种是系统级的 文件句柄限制,就是规定的单个进程能够打开的最大文件句柄数量(Socket连接也算在里面,默认大小1024) 1 用户级的修改 1.1 ...

  2. ASP.NET Core 3.0 解决无法将“Add-Migration”项识别为 cmdlet、函数、脚本文件或可运行程序的名称错误

    写在前面 在 ASP.NET Core 的项目中 使用 CodeFirst 的模式,进行初始化迁移时.出现如图所示的问题: 在度娘哪里查了半天之后,才从这个帖子里找到了答案.传送门 分析原因 ASP. ...

  3. Delphi - 鼠标上下滚动基础消息事件

    Delphi实现对鼠标上下滚动基础消息的截获并处理 前几天有客户提出需求:由于个人PC界面限制,有时候电子图档显示不全,希望通过鼠标上下滚动用来控制电子图档的放大和缩小. 下面通过一个测试Demo来说 ...

  4. 通俗易懂的讲解一下Java的代理模式

    一.基本概念 代理模式是对象的结构模式. 代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用(接口的引用) 二.静态代理 静态代理是指,代理类在程序运行前就已经定义好,其与**目标类 ...

  5. 2019 蓝鲸人java面试笔试题 (含面试题解析)

      本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.蓝鲸人等公司offer,岗位是Java后端开发,因为发展原因最终选择去了蓝鲸人,入职一年时间了,也成为了面试官 ...

  6. 编译OpenCV提示opencv_contrib缺少boostdesc_bgm.i等文件

    错误提示: ~/opencv_contrib/modules/xfeatures2d/src/boostdesc.:: fatal error: boostdesc_bgm.i: No such fi ...

  7. 使用vue导出excel文件

    今天再开发中遇到一件事情,就是怎样用已有数据导出excel文件,网上有许多方法,有说用数据流的方式,https://www.cnblogs.com/yeqrblog/p/9758981.html,但是 ...

  8. javascript高级程序设计学习历程

    第三章 基本概念 3.1 语法 3.1.1 区分大小写 ECMAScript中的一切(变量,函数,操作符)都区分大小写的 3.1.2 标识符 标识符:变量,函数,属性的名字以及函数的参数. 标识符的命 ...

  9. 攻防世界 高手进阶区 web cat

    php cURL CURLOPT_SAFE_UPLOAD django DEBUG mode Django使用的是gbk编码,超过%F7的编码不在gbk中有意义 当 CURLOPT_SAFE_UPLO ...

  10. 隐马尔科夫模型(Hidden Markov Models) 系列之二

    转自:http://blog.csdn.net/eaglex/article/details/6385204 隐含模式(Hidden Patterns) 当马尔科夫过程不够强大的时候,我们又该怎么办呢 ...