快速业务通道

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

作者 佚名技术 来源 程序设计 浏览 发布时间 2012-06-30
set(0, 0);
    bool cpp_exc = ExceptionRecord->ExceptionCode == MS_CPP_EXC;
    get_exception(ExceptionRecord, &pcur_exc);
    get_excpt_info(ExceptionRecord, &pexc_info);
    if(cpp_exc && 0 == pcur_exc && 0 == pexc_info) //重新抛出
    {
      ExceptionRecord->ExceptionInformation[1] = reinterpret_cast<DWORD>(pprev_exc);
      ExceptionRecord->ExceptionInformation[2] = reinterpret_cast<DWORD>(pprev_excinfo);
    }
    else
    {
      exception_helper::destroy(pprev_exc, pprev_excinfo);
    }
  }
  return ExceptionContinueSearch;
}
下面是get_exception_storage()函数的一个实现:
exception_storage* get_exception_storage()
{
  static exception_storage es;
  return &es;
}
  在单线程程序中,这是一个完美的实现。但在多线程中,这就是个灾难了,想象一下多个线程访问它,并把异常对象保存在里面的情景吧。由于每个线程都有自己的堆栈和异常处理链,我们需要一个线程安全的get_exception_storage实现:每个线程都有自己单独的exception_storage,它在线程启动时被创建,并在结束时被销毁。Windows提供的线程局部存储(thread local storage,TLS)可以满足这个要求,它能让每个线程通过一个全局键值来访问为这个线程所私有的对象副本,这是通过TlsGetValue()和TlsSetValue这两个API来完成的。
  Excptstorage.cpp中给出了get_exception_storage()函数的实现。它会被编译成动态链接库,因为我们可以籍此知道线程的创建和退出——系统在这两种情况下都会调用所有(当前进程加载的)dll的DllMain()函数,这让我们有机会创建特定于线程的数据,也就是exception_storage对象。
//excptstorage.cpp
#include "excptstorage.h"
#include <windows.h>
namespace
{
  DWORD dwstorage;
}
namespace my_handler
{
  __declspec(dllexport) exception_storage* get_exception_storage() throw ()
  {
    void * p = TlsGetValue(dwstorage);
    return reinterpret_cast <exception_storage*>(p);
  }
}
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
  using my_handler::exception_storage;
  exception_storage *p;
  switch (ul_reason_for_call)
  {
  case DLL_PROCESS_ATTACH:
    //主线程(第一个线程)不会收到DLL_THREAD_ATTACH通知,所以,
    //与其相关的操作也放在这了
    dwstorage = TlsAlloc();
    if (-1 == dwstorage)
      return FALSE;
    p = new exception_storage();
    TlsSetValue(dwstorage, p);
    break ;
  case DLL_THREAD_ATTACH:
    p = new exception_storage();
    TlsSetValue(dwstorage, p);
    break;
  case DLL_THREAD_DETACH:
    p = my_handler::get_exception_storage();
    delete p;
    break ;
  case DLL_PROCESS_DETACH:
    p = my_handler::get_exception_storage();
    delete p;
    break ;
  }
  return TRUE;
}


  结论

综上所述,异常处理是在操作系统的协助下,由C++编译器和运行时异常处理库共同完成的。

注释和参考资料

① 本文写作期间,微软发布了Visual Studio 7.0。本文的异常处理库主要是在运行于奔腾处理器的windows2000上使用VC++6.0编译和测试的。但我也在VC++5.0和VC++7.0 beta版上测试过。6.0和7.0之间有一些差别,6.0先把异常(或其引用)拷

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站: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号