快速业务通道

C++编译器如何实现异常处理

作者 佚名技术 来源 程序设计 浏览 发布时间 2012-06-30
st(my_hdlr) - (reinterpret_cast(cpp_hdlr) + 5);
    if(!saved_handler_instructions)
    {
      if(!ReadMemory(cpp_hdlr, cpp_handler_instructions, sizeof(cpp_handler_instructions)))
        return false;
      saved_handler_instructions = true;
    }
    return WriteMemory(cpp_hdlr, &jmp_my_hdlr, sizeof(jmp_my_hdlr));
  }
  bool restore_cpp_handler()
  {
    if(!saved_handler_instructions)
      return false;
    else
    {
      void* loc = __CxxFrameHandler;
      return WriteMemory(loc, cpp_handler_instructions, sizeof(cpp_handler_instructions));
    }
  }
}
  编译指令#pragma pack(push, 1)告诉编译器不要在jmp_instr结构中填充任何用于对齐的空间。没有这条指令,jmp_instr的大小将是8字节,而我们需要它是5字节。
  现在重新回到异常处理这个主题上来。调用catch块时,它可能重新抛出异常或抛出新异常。前一种情况下,异常处理程序必须继续传播(propagate)当前异常;后一种情况下,它需要在继续之前销毁原来的异常。此时,处理程序要面对两个难题:“如何知道异常是源于catch块还是程序的其他部分”和“如何跟踪原来的异常”。我的解决方法是:在调用catch块之前,把当前异常保存在exception_storage对象中,并注册一个专用于catch块的异常处理程序——catch_block_protector。调用get_exception_storage()函数,就能得到exception_storage对象:
exception_storage* p = get_exception_storage();
p->set(pexc, pexc_info);
注册 catch_block_protector;

调用catch块; //....

这样,当catch块(重新)抛出异常时,程序将会执行catch_block_protector。如果是抛出了新异常,这个函数可以从exception_storage对象中分离出前一个异常并销毁它;如果是重新抛出原来的异常(可以通过ExceptionInformation数组的前两个元素知道是新异常还是旧异常,后一种情况下着两个元素都是0,参见下面的代码),就通过拷贝ExceptionInformation数组来继续传播它。下面的代码就是catch_block_protector()函数的实现。

//-------------------------------------------------------------------
// 如果这个处理程序被调用了,可以断定是catch块(重新)抛出了异常。
// 异常处理程序(my_handler)在调用catch块之前注册了它。其任务是判断
// catch块抛出了新异常还是重新抛出了原来的异常,并采取相应的操作。
// 在前一种情况下,它需要销毁传递给catch块的前一个异常对象;在后一种
// 情况下,它必须找到原来的异常并将其保存到ExceptionRecord中供异常
// 处理程序使用。
//-------------------------------------------------------------------
EXCEPTION_DISPOSITION catch_block_protector(
    _EXCEPTION_RECORD* ExceptionRecord,
    void* EstablisherFrame,
    struct _CONTEXT *ContextRecord,
    void* DispatcherContext
    ) throw ()
{
  EXCEPTION_REGISTRATION *pFrame;
  pFrame= reinterpret_cast<EXCEPTION_REGISTRATION*>(EstablisherFrame);
  if(!(ExceptionRecord->ExceptionFlags & (_EXCEPTION_UNWINDING | _EXCEPTION_EXIT_UNWIND)))
  {
    void *pcur_exc = 0, *pprev_exc = 0;
    const excpt_info *pexc_info = 0, *pprev_excinfo = 0;
    exception_storage* p = get_exception_storage();
    pprev_exc = p->get_exception();
    pprev_excinfo = p->get_exception_info();
    p->

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号