9
votes

Existe-t-il une fonction pour convertir EXCEPTION_Pointers STRIT à une chaîne?

Est-ce que quelqu'un connaît une fonction pour convertir la structure d'exception_points-signes revenue de GetExceptionInformation () dans une chaîne que je peux vous connecter?

Je ne veux pas rouler le mien si cela a déjà été fait.

Modifier: Fondamentalement, j'ai ajouté les blocs __try {} __except () {} Blocks pour aider l'application échoue gracieusement sur une erreur critique. Pendant que je suis là, j'essaie de vous connecter aussi détaillé d'un message d'erreur que possible pour localiser le problème pour que nous puissions résoudre. Idéalement, j'aimerais imprimer le nom de fichier et la ligne d'échec de l'échec, mais je doute que cela soit possible, je espère donc jeter toutes les informations d'exception dans les espoirs que nous pourrons venir aussi près que possible que possible. identifier la cause exacte du problème.


0 commentaires

5 Réponses :


4
votes

Il n'y a pas de cette fonction de ce type, car vous aurez besoin de symboles privés pour écrire quelque chose de significatif. Le dbghelp.dll aide à certains de ceci (spécifiquement le Fonction StackWalk et sa variante 64 bits)

Que voulez-vous sortir de l'enregistrement d'exception pour mettre dans le journal? Juste le code d'exception? Le contexte de registre? Le backtrage de la pile?

edit: aussi, si vous ne faites que rien, mais inscrivez-vous pour Rapport d'erreur Windows , vous pouvez simplement utiliser le service génial de Microsoft et obtenir les décharges de crash, seau par la popularité. Si vous le pouvez, c'est de loin le meilleur moyen d'enregistrer des décharges de crash.


0 commentaires

2
votes

1 commentaires

Je dirais que juste le code et l'adresse n'est pas particulièrement utile, en particulier avec ASLR sur Vista / Win7, puisque vous n'avez pas enregistré la base du module.



2
votes

Il n'y en a pas beaucoup, vous ne serez plus intéressé par le code d'exception et l'adresse. Si l'exception est une exception_access_violation, vous souhaitez également jeter les deux premières valeurs d'informations exceptionnelles. Le premier indique l'opération (0 = lecture, 1 = écrire, 8 = prévention de l'exécution de données), la seconde donne l'adresse de défaut.


1 commentaires

En dehors de 0 et 1, il y a aussi 8, "si cette valeur est 8, le thread provoque une violation de la prévention de l'exécution de données de l'utilisateur (DEP)." de "exception_record structure" MSDN. Microsoft.com/en-us/Library/windows/desktop/...



17
votes
// 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;
}

0 commentaires