代码之家  ›  专栏  ›  技术社区  ›  John MacIntyre

是否有函数将异常指针结构转换为字符串?

  •  7
  • John MacIntyre  · 技术社区  · 15 年前

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

    EDIT:基本上,我添加了{uu try{}}uuu except(){}块来帮助应用程序在出现严重错误时正常地失败。当我在做这件事的时候,我会尽可能详细地记录一条错误消息,以便找到问题并解决。理想情况下,我想打印出文件名和它失败的行,但我怀疑这是可能的,所以我希望转储所有的异常信息,希望我们能够尽可能地找出问题的确切原因。

    5 回复  |  直到 15 年前
        1
  •  4
  •   John MacIntyre    15 年前

    没有这样的函数,因为你需要私人符号来写任何有意义的东西。这个数据库帮助.dll有助于解决一些问题(特别是 StackWalk function 以及它的64位变体)

    您想从异常记录中得到什么来放入日志中?只是例外代码?寄存器上下文?堆栈回溯?

    另外,如果你什么都不做,只是注册 Windows Error Reporting ,你只需使用微软令人敬畏的服务,并获得崩溃转储回来,由人气扣。如果可以的话,这是迄今为止记录崩溃转储的最好方法。

        2
  •  16
  •   Alessandro Jacopson    12 年前
    // 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;
    }
    
        3
  •  2
  •   Knowles Atchison    15 年前

    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;
        }
    }
    
        4
  •  2
  •   Hans Passant    13 年前

    没有什么,你只会对异常代码和地址感兴趣。如果异常是异常访问冲突,那么您还需要转储前两个异常信息值。第一个表示操作(0=读取,1=写入,8=数据执行防止),第二个表示错误地址。

        5
  •  1
  •   jlguenego    11 年前

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