【问题标题】:Is there a function to convert EXCEPTION_POINTERS struct to a string?是否有将 EXCEPTION_POINTERS 结构转换为字符串的函数?
【发布时间】:2011-04-01 05:22:39
【问题描述】:

有人知道一个函数可以将 GetExceptionInformation() 返回的 EXCEPTION_POINTERS 结构转换为我可以记录的字符串吗?

如果已经完成,我不想自己动手。

编辑:基本上,我添加了 __try{} __except(){} 块来帮助应用程序在严重错误时优雅地失败。在此过程中,我正在尝试尽可能详细地记录错误消息,以找到我们要解决的问题。理想情况下,我想打印出文件名和失败的行,但我怀疑这是可能的,所以我希望转储所有异常信息,希望我们能够尽可能接近找出问题的确切原因。

【问题讨论】:

    标签: c++ windows visual-c++ exception winapi


    【解决方案1】:

    没有这样的功能,因为你需要私有符号来写任何有意义的东西。 dbghelp.dll 有助于解决其中的一些问题(特别是 StackWalk function 及其 64 位变体)

    你想从异常记录中取出什么放入日志?只是异常代码?寄存器上下文?堆栈回溯?

    编辑:另外,如果您什么都不做,而是注册Windows Error Reporting,您可以使用 Microsoft 的超棒服务并恢复崩溃转储,并受到受欢迎程度的影响。如果可以的话,这是迄今为止记录故障转储的最佳方式。

    【讨论】:

      【解决方案2】:

      From here.

      #include <windows.h>
      #include <iostream>
      #include <string.h>
      #include <eh.h>
      using namespace std;
      
      static void translateSEH(unsigned int u, EXCEPTION_POINTERS* pExcept) {
        // Translate SEH exception to a C++ exception.  NOTE: compiling with /EHa is required!!
        static char msg[256];
        sprintf_s(msg, 256, "Unhandled exception 0x%08x at 0x%08x",
          pExcept->ExceptionRecord->ExceptionCode,
          pExcept->ExceptionRecord->ExceptionAddress);
        throw exception(msg);
      }
      
      int main(){
        _set_se_translator(translateSEH);
          int p = 0;
          try {
              cout<<1 / p<<endl;   
          }
        catch (std::exception& ex) {
              cout << ex.what() << endl;
          }
      }
      

      【讨论】:

      • 我认为只是代码和地址并不是特别有用,尤其是在 Vista/Win7 上使用 ASLR,因为您没有记录模块库
      【解决方案3】:

      没有太多内容,您只会对异常代码和地址感兴趣。如果异常是 EXCEPTION_ACCESS_VIOLATION 那么您还想转储前两个 ExceptionInformation 值。第一个表示操作(0=读,1=写,8=数据执行防止),第二个给出故障地址。

      【讨论】:

      【解决方案4】:
      // Compile with /EHa
      #include <windows.h>
      #include <eh.h>
      #include <Psapi.h>
      #include <string>
      #include <sstream>
      
      class InfoFromSE
      {
      public:
         typedef unsigned int exception_code_t;
      
         static const char* opDescription( const ULONG opcode )
         {
            switch( opcode ) {
            case 0: return "read";
            case 1: return "write";
            case 8: return "user-mode data execution prevention (DEP) violation";
            default: return "unknown";
            }
         }
      
         static const char* seDescription( const exception_code_t& code )
         {
            switch( code ) {
               case EXCEPTION_ACCESS_VIOLATION:         return "EXCEPTION_ACCESS_VIOLATION"         ;
               case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:    return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED"    ;
               case EXCEPTION_BREAKPOINT:               return "EXCEPTION_BREAKPOINT"               ;
               case EXCEPTION_DATATYPE_MISALIGNMENT:    return "EXCEPTION_DATATYPE_MISALIGNMENT"    ;
               case EXCEPTION_FLT_DENORMAL_OPERAND:     return "EXCEPTION_FLT_DENORMAL_OPERAND"     ;
               case EXCEPTION_FLT_DIVIDE_BY_ZERO:       return "EXCEPTION_FLT_DIVIDE_BY_ZERO"       ;
               case EXCEPTION_FLT_INEXACT_RESULT:       return "EXCEPTION_FLT_INEXACT_RESULT"       ;
               case EXCEPTION_FLT_INVALID_OPERATION:    return "EXCEPTION_FLT_INVALID_OPERATION"    ;
               case EXCEPTION_FLT_OVERFLOW:             return "EXCEPTION_FLT_OVERFLOW"             ;
               case EXCEPTION_FLT_STACK_CHECK:          return "EXCEPTION_FLT_STACK_CHECK"          ;
               case EXCEPTION_FLT_UNDERFLOW:            return "EXCEPTION_FLT_UNDERFLOW"            ;
               case EXCEPTION_ILLEGAL_INSTRUCTION:      return "EXCEPTION_ILLEGAL_INSTRUCTION"      ;
               case EXCEPTION_IN_PAGE_ERROR:            return "EXCEPTION_IN_PAGE_ERROR"            ;
               case EXCEPTION_INT_DIVIDE_BY_ZERO:       return "EXCEPTION_INT_DIVIDE_BY_ZERO"       ;
               case EXCEPTION_INT_OVERFLOW:             return "EXCEPTION_INT_OVERFLOW"             ;
               case EXCEPTION_INVALID_DISPOSITION:      return "EXCEPTION_INVALID_DISPOSITION"      ;
               case EXCEPTION_NONCONTINUABLE_EXCEPTION: return "EXCEPTION_NONCONTINUABLE_EXCEPTION" ;
               case EXCEPTION_PRIV_INSTRUCTION:         return "EXCEPTION_PRIV_INSTRUCTION"         ;
               case EXCEPTION_SINGLE_STEP:              return "EXCEPTION_SINGLE_STEP"              ;
               case EXCEPTION_STACK_OVERFLOW:           return "EXCEPTION_STACK_OVERFLOW"           ;
               default: return "UNKNOWN EXCEPTION" ;
            }
         }
      
         static std::string information( struct _EXCEPTION_POINTERS* ep, bool has_exception_code = false, exception_code_t code = 0  )
         {
            HMODULE hm;
            ::GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, static_cast<LPCTSTR>(ep->ExceptionRecord->ExceptionAddress), &hm );
            MODULEINFO mi;
            ::GetModuleInformation( ::GetCurrentProcess(), hm, &mi, sizeof(mi) );
            char fn[MAX_PATH];
            ::GetModuleFileNameExA( ::GetCurrentProcess(), hm, fn, MAX_PATH );
      
            std::ostringstream oss;
            oss << "SE " << (has_exception_code?seDescription( code ):"") << " at address 0x" << std::hex << ep->ExceptionRecord->ExceptionAddress << std::dec 
               << " inside " << fn << " loaded at base address 0x" << std::hex << mi.lpBaseOfDll << "\n"; 
      
            if ( has_exception_code && (
                 code == EXCEPTION_ACCESS_VIOLATION || 
                 code == EXCEPTION_IN_PAGE_ERROR ) ) {
               oss << "Invalid operation: " << opDescription(ep->ExceptionRecord->ExceptionInformation[0]) << " at address 0x" << std::hex << ep->ExceptionRecord->ExceptionInformation[1] << std::dec << "\n";
            }
      
            if ( has_exception_code && code == EXCEPTION_IN_PAGE_ERROR ) {
               oss << "Underlying NTSTATUS code that resulted in the exception " << ep->ExceptionRecord->ExceptionInformation[2] << "\n";
            }
      
            return oss.str();
         }
      };
      
      #include <iostream>
      #include <exception>
      
      void translator( InfoFromSE::exception_code_t code, struct _EXCEPTION_POINTERS* ep )
      {
         throw std::exception( InfoFromSE::information(ep,true,code).c_str() );
      }
      
      int main(int argc, char* argv[])
      {
         _set_se_translator(translator);
         try{
            int* p = 0;
            std::cout << *p;
         }catch( const std::exception& e ){
            std::cerr << e.what() << "\n";
         }
      
         try{
            int* p = 0;
            *p = 0;
            std::cout << *p;
         }catch( const std::exception& e ){
            std::cerr << e.what() << "\n";
         }
      
         try{
            int a = 42;
            volatile int b = 0;
            std::cout << a/b;
         }catch( const std::exception& e ){
            std::cerr << e.what() << "\n";
         }
          return 0;
      }
      

      【讨论】:

        【解决方案5】:

        您可以在以下位置查看 microsoft 代码:http://support.microsoft.com/kb/259693 也可以查看这段小代码:http://www.codeproject.com/Articles/6503/An-NTSTATUS-lookup-application

        【讨论】:

          猜你喜欢
          • 2021-04-23
          • 1970-01-01
          • 1970-01-01
          • 2015-12-30
          • 2011-07-16
          • 1970-01-01
          • 2021-06-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多