C++——windows结构异常转化成C++异常

C++异常和Windows结构异常的比较
Windows结构异常有如下几个特性:
1、它使用__try、__except、__finally和__leave关键字和RaiseException API。
2、它由Windows所支持,因此它不适合其它操作系统。
3、它不处理C++对象的解析。
4、它用为硬件异常(例如访问非法或被零除)或操作系统异常的结果被抛出。也可以作为RaiseException函数的结果被抛出;
说明:在使用Windows结构异常的函数内,如果有C++对象,编译器会发
出:error C2712: Cannot use __try in functions that require object unwinding 的错误。
如:

void fun( )
{
        CObject       object ;         // 错误!结构化异常无法解析C++ 对象
        __try{
           ...
        }
        __except(...){
                     ...
              }
}//程序使用SEH (Structured Exception Handling)异常模型的 try-except 语法

同样还是由于在一个函数不能采用两种形式的异常处理机制而导致的编译错误。在 C++ 异常处理模型中,为了能够在异常发生后,保证正确地释放相关的局部变量(也即调用析构函数),它必须要跟踪每一个“对象”的创建过程,这种由于异常产生而导致的对象析构的过程,被称为“ unwind ”。因此,如果一个函数中有局部对象的存在,那么它就一定会存在 C++ 的异常处理机制(也即会给此函数插入一些用于 C++ 异常处理“代码和信息”),这样,如果该函数中在再使用 try-except 机制,岂不是就冲突了吗?所以编译器也就报错了,因为它处理不了了。
而C++异常的特点是:
1、使用try、throw和catch等关键字;
2、它处理C++对象的解析;
3、它作为throw语句的结果被抛出;
注:MFC提供了第三种异常处理机制。它使用几个异常处理宏,这些宏现在也被编译成C++异常,因此没有必要在新的代码中使用它们!在MFC编程中,异常对象都是从CExcept派生。大多数MFC异常处理对象都是动态分配的,因此当它们被捕获时,必须被删除;而没有捕获的MFC异常由MFC本身在AfxCa-llWndProc函数中捕获并删除。

因为C++异常不能处理硬件和操作系统异常,因此需要将结构异常转化为
C++异常。如何将结构异常转化为C++异常?
Visual C++ 允许你通过使用_set_se_translator函数将结构异常转化为C++异常。

namespace custom_util
{
      class se_exception: public std::exception
      {
      public:
            se_exception() {}
            ~se_exception() {}
            virtual const char* what() const  { return m_detail.c_str(); }
            static void set_se_to_ce_translator() {_set_se_translator(se_to_ce_translator);}
      private:
            se_exception(const string& detail){ m_detail = detail;  }
            static void _cdecl se_to_ce_translator(unsigned int ec, PEXCEPTION_POINTERS pep) 
            {
                  char a[50]={0};
                 sprintf_s(a,"err=0x%X  addr=0x%X",pep->ExceptionRecord->ExceptionCode,
                       pep->ExceptionRecord->ExceptionAddress);
                  string detail(a);
                  throw se_exception(detail);
            }
      private:
            string m_detail;
      };
#define SET_ONCE_THREAD_SE_TRANSLATOR() {\
      static DWORD thread_id = 0;\
      if (thread_id == 0)\
      {\
      custom_util::se_exception::set_se_to_ce_translator();\
      thread_id = GetCurrentThreadId();\
      }}
}

异常转化器在每个线程的基础上进行工作,因此你需要为每一个线程安装一个转化器。这种异常转化器有一个副作用,你会在输出窗口的Debug标签中看见两个异常跟踪消息:一个是为了原来的结构异常,另一个是为了转化后的C++异常。使用了异常转化器后,就可以像捕获C++异常一样捕获结构异常。
**在线程或者主函数中调用时:

      SET_ONCE_THREAD_SE_TRANSLATOR();
      try{  
          int * a= reinterpret_cast< int * > (01);  
          *a=0; 
          }
      catch(std::exception& e)//抛出的是se_exception异常,what()虚函数的调用是se_exception的。
      {     cout << e.what();  }
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值