C++ RTTI in a Windows 64-bit VectoredExceptionHandler, MS Visual Studio 2015 -


i'm working on small windows exception handling engine trying gather maximum information system, including c++ exceptions rtti.

in 32-bit vectoredexceptionhandler compiled msvs 2015, can obtain std::type_info pointer rtti of type being thrown. can found in ((_throwinfo*) exceptionpointers->exceptionrecord->exceptioninformation[2])->pcatchabletypearray->arrayofcatchabletypes[0] (see classic article of raymond chen, definitions ms's ehdata.h file , many others). method based on fetching pcatchabletypearray member of msvc built-in _throwinfo structure data built compiler.

but in 64-bit environment, _throwinfo contains no direct rtti: unfortunately, pcatchabletypearray null. in disassembly window, see null before call _cxxthrowexception, main ms throw-handler. searched through number of articles concerning new 64-bit exception-handling mechanism used in msvc, there no information on rtti. maybe missed something.

are there ways obtain std::type_info (or type name) of c++ exception being thrown in vectored exception handler working in 64-bit msvc environment?

here's output of dumping 32-bit , 64-bit exception info:

32-bit (rtti success):

vectoredexceptionhandler(): start  exc->exceptioncode               = 0xe06d7363 exc->exceptionaddress            = 0x74e2c54f exc->numberparameters            = 3 exc->exceptioninformation[0]     = 0x19930520 (sig) exc->exceptioninformation[1]     = 0x004ffd9c (object) exc->exceptioninformation[2]     = 0x003ad85c (throwinfo) exc->exceptioninformation[3]     = 0x005b18f8 (module)  throwinfo->attributes            = 0x00000000 throwinfo->pmfnunwind            = 0x00000000 throwinfo->pforwardcompat        = 0x00000000 throwinfo->pcatchabletypearray   = 0x003ad870  object    = 0x004ffd9c throwinfo = 0x003ad85c module    = 0x00000000  throwinfo->pcatchabletypearray   = 0x003ad870 carray                           = 0x003ad870  carray->arrayofcatchabletypes[0] = 0x003ad878 ctype                            = 0x003ad878  ctype->ptype                     = 0x003afa70 type                             = 0x003afa70  type->name()                     = "struct `int __cdecl main(void)'::`2'::meow_exception" ctype->sizeoroffset              = 4  vectoredexceptionhandler(): end  main(): catch (meow_exception { 3 }) 

64-bit (rtti failure)

vectoredexceptionhandler(): start  exc->exceptioncode               = 0xe06d7363 exc->exceptionaddress            = 0x000007fefce0a06d exc->numberparameters            = 4 exc->exceptioninformation[0]     = 0x0000000019930520 (sig) exc->exceptioninformation[1]     = 0x000000000025fbe0 (object) exc->exceptioninformation[2]     = 0x000000013fc52ab0 (throwinfo) exc->exceptioninformation[3]     = 0x000000013fbe0000 (module)  module                           = 0x000000013fbe0000  throwinfo->attributes            = 0x00000000 throwinfo->pmfnunwind            = 0x0000000000000000 throwinfo->pforwardcompat        = 0x0000000000072ad0 throwinfo->pcatchabletypearray   = 0x0000000000000000  vectoredexceptionhandler(): end  main(): catch (meow_exception { 3 }) 

the code used these dumps:

#include <stdio.h> #include <typeinfo> #include <windows.h>  //--------------------------------------------------------------------------------------------------  const unsigned exception_cpp_microsoft                  = 0xe06d7363,  // '?msc'                exception_cpp_microsoft_eh_magic_number1 = 0x19930520,  // '?msc' version magic, see ehdata.h                 exception_output_debug_string            = 0x40010006,  // outputdebugstring() call                exception_thread_name                    = 0x406d1388;  // passing name of thread debugger  void outputdebugprintf (const char* format, ...);  //--------------------------------------------------------------------------------------------------  long winapi vectoredexceptionhandler (exception_pointers* pointers)     {     const exception_record* exc = pointers->exceptionrecord;      if (exc->exceptioncode == exception_output_debug_string ||         exc->exceptioncode == exception_thread_name)         return exception_continue_search;      outputdebugprintf ("\n%s(): start\n\n", __func__);      outputdebugprintf ("exc->exceptioncode    = 0x%x\n", exc->exceptioncode);     outputdebugprintf ("exc->exceptionaddress = 0x%p\n", exc->exceptionaddress);      if (exc->exceptioninformation[0] == exception_cpp_microsoft_eh_magic_number1 &&          exc->numberparameters >= 3)         {         outputdebugprintf ("exc->numberparameters = %u\n", exc->numberparameters);          outputdebugprintf ("exc->exceptioninformation[0] = 0x%p (sig)\n",       (void*) exc->exceptioninformation[0]);         outputdebugprintf ("exc->exceptioninformation[1] = 0x%p (object)\n",    (void*) exc->exceptioninformation[1]);         outputdebugprintf ("exc->exceptioninformation[2] = 0x%p (throwinfo)\n", (void*) exc->exceptioninformation[2]);         outputdebugprintf ("exc->exceptioninformation[3] = 0x%p (module)\n",    (void*) exc->exceptioninformation[3]);         outputdebugprintf ("\n");          hmodule module = (exc->numberparameters >= 4)? (hmodule) exc->exceptioninformation[3] : null;          if (module)             {             outputdebugprintf ("module = 0x%p\n", module);             outputdebugprintf ("\n");             }          const _throwinfo* throwinfo = (const _throwinfo*) exc->exceptioninformation[2];          if (throwinfo)             {             outputdebugprintf ("throwinfo->attributes          = 0x%08x\n", throwinfo->attributes);             outputdebugprintf ("throwinfo->pmfnunwind          = 0x%p\n",   throwinfo->pmfnunwind);             outputdebugprintf ("throwinfo->pforwardcompat      = 0x%p\n",   throwinfo->pforwardcompat);             outputdebugprintf ("throwinfo->pcatchabletypearray = 0x%p\n",   throwinfo->pcatchabletypearray);             outputdebugprintf ("\n");             }          if (throwinfo && throwinfo->pcatchabletypearray)             {                           #define rva_to_va_(type, addr)  ( (type) ((uintptr_t) module + (uintptr_t) (addr)) )              outputdebugprintf ("object    = 0x%p\n", (void*) exc->exceptioninformation[1]);             outputdebugprintf ("throwinfo = 0x%p\n", (void*) throwinfo);             outputdebugprintf ("module    = 0x%p\n", (void*) module);             outputdebugprintf ("\n");              const _catchabletypearray* carray = rva_to_va_(const _catchabletypearray*, throwinfo->pcatchabletypearray);              outputdebugprintf ("throwinfo->pcatchabletypearray = 0x%p\n",   (void*) throwinfo->pcatchabletypearray);             outputdebugprintf ("carray                         = 0x%p\n\n", (void*) carray);              const _catchabletype* ctype = rva_to_va_(const _catchabletype*, carray->arrayofcatchabletypes[0]);              outputdebugprintf ("carray->arrayofcatchabletypes[0] = 0x%p\n",   (void*) carray->arrayofcatchabletypes[0]);             outputdebugprintf ("ctype                            = 0x%p\n\n", (void*) ctype);              const std::type_info* type = rva_to_va_(const std::type_info*, ctype->ptype);              outputdebugprintf ("ctype->ptype = 0x%p\n",   (void*) ctype->ptype);             outputdebugprintf ("type         = 0x%p\n\n", (void*) type);              outputdebugprintf ("type->name()        = \"%s\"\n", type->name());             outputdebugprintf ("ctype->sizeoroffset = %zu\n\n",  (size_t) ctype->sizeoroffset);              #undef rva_to_va_             }         }      outputdebugprintf ("%s(): end\n", __func__);     return exception_continue_search;     }  //--------------------------------------------------------------------------------------------------  void outputdebugprintf (const char* format, ...)     {     static char buf [1024] = "";      va_list arg; va_start (arg, format);     _vsnprintf_s (buf, sizeof (buf) - 1, _truncate, format, arg);     va_end (arg);      outputdebugstring (buf);     printf ("%s", buf);     }  //--------------------------------------------------------------------------------------------------  int main()     {         outputdebugprintf ("\n%s(): start\n", __func__);      addvectoredexceptionhandler (1, vectoredexceptionhandler);      struct meow_exception { int code = 3; };      try         {         throw meow_exception();         }      catch (const meow_exception& e)         {         outputdebugprintf ("\n%s(): catch (meow_exception { %d })\n", __func__, e.code);         }      catch (...)         {         outputdebugprintf ("\n%s(): catch (...)\n", __func__);         }      outputdebugprintf ("\n%s(): end\n", __func__);     return 0;     } 

build options:

// microsoft (r) c/c++ optimizing compiler version 19.00.24213.1 (part of vs 2015 sp3)  cl   /c code.cpp /ehsc /w4 link    code.obj kernel32.lib /machine:x86 /subsystem:console /debug 

thank in advance answers , advices.

to solve problem gone deeper research , discovered interesting things concerning msvc 64-bit mode. i've found can not rely on internal compiler-predefined types in 64-bit mode because of them wrong.

i compared definitions of internal structures predefined compiler, such _throwinfo , _catchabletype, assembly listings produced compiler being run /fas command-line switch.

here instances of these structures extracted assembly files (below msvc 2015 64-bit version):

;--------------------------------------------------------------------------------------- ; listing generated microsoft optimizing compiler version 19.00.24213.1  ; simplified: many lines skipped, sections reordered etc -- ded ;---------------------------------------------------------------------------------------  main proc  ;   struct meow_exception { int code = 3; }; ;    ;   try ;       { ;       throw meow_exception();      ...     lea  rdx, offset flat:_ti1?aumeow_exception@?1??main@@yahxz@  ; lea &_throwinfo     lea  rcx, qword ptr $t1[rsp]     call _cxxthrowexception  ;--------------------------------------------------------------------------------------- _ti1?aumeow_exception@?1??main@@yahxz@                            ; _throwinfo     dd  0     dd  0     dd  0     dd  imagerel _cta1?aumeow_exception@?1??main@@yahxz@          ; &_catchabletypearray  ;--------------------------------------------------------------------------------------- _cta1?aumeow_exception@?1??main@@yahxz@                           ; _catchabletypearray     dd  1     dd  imagerel _ct??_r0?aumeow_exception@?1??main@@yahxz@@84    ; &_catchabletype  ;--------------------------------------------------------------------------------------- _ct??_r0?aumeow_exception@?1??main@@yahxz@@84                     ; _catchabletype     dd  0     dd  imagerel ??_r0?aumeow_exception@?1??main@@yahxz@@8        ; &_typedescriptor     dd  0     dd  0ffffffffh     org $+4     dd  04h     dd  0  ;--------------------------------------------------------------------------------------- ??_r0?aumeow_exception@?1??main@@yahxz@@8         ; _typedescriptor (aka std::type_info)     dq  flat:??_7type_info@@6b@     dq  0     db  '.?aumeow_exception@?1??main@@yahxz@', 0  ; mangled type name  ;--------------------------------------------------------------------------------------- 

the binary layout of 32-bit version of these structures similar 64-bit, little differences (flat modifier instead of imagerel in address fields , dd instead of dq in _typedescriptor).

then, let's compare listing predefined types taken ehdata.h file (f.e., see well-known source geoff chappell or c:\program files (x86)\microsoft visual studio 12.0\vc\crt\src\ehdata.h file in msvc 2013; unfortunately file doesn't exist in msvc 2015 runtime sources):

typedef const struct _s__throwinfo     {     unsigned int         attributes;     _pmfn                pmfnunwind;            // pointer!     int (__cdecl        *pforwardcompat) (...); // pointer too!     _catchabletypearray *pcatchabletypearray;   // pointer too!     }     _throwinfo;  typedef const struct _s__catchabletype     {     unsigned int     properties;     _typedescriptor *ptype;                     // pointer too!     _pmd             thisdisplacement;     int              sizeoroffset;     _pmfn            copyfunction;              // pointer too!     }     _catchabletype; 

in 32-bit mode, ok because pointers 32-bit , predefined internal definitions of structures correspond assembly listings.

in 64-bit mode, pointers in these structures rvas (relative virtual addresses) measured image base of module. known , well-documented feature; corresponds assembler listing above. notice imagerel address modifiers, these mean rvas. these rvas 32-bit , defined 32-bit dd keyword.

but in 64-bit mode, c++ side, corresponding pointers considered 64-bit. thus, c++ binary layout of internal compiler structures containing pointers (such _throwinfo or _catchabletype above) does not correspond assembler binary layout. sizes of these structures greater c++ side, , fields offsets wrong too.

to test this, defined own custom structures same fields represented 32-bit integer types instead of pointers:

namespace correct     {     struct throwinfo         {         __int32 attributes;         __int32 pmfnunwind;           // 32-bit rva         __int32 pforwardcompat;       // 32-bit rva         __int32 pcatchabletypearray;  // 32-bit rva         };      struct catchabletype         {         __int32 properties;         __int32 ptype;                // 32-bit rva         _pmd    thisdisplacement;         __int32 sizeoroffset;         __int32 copyfunction;         // 32-bit rva         };     } 

then dumped contents of _throwinfo , _catchabletype using both internal definitions , own definitions. here's result (msvc 2015 64-bit):

exc->exceptioncode               = 0xe06d7363 exc->exceptionaddress            = 0x000007fefd69a06d exc->numberparameters            = 4 exc->exceptioninformation[0]     = 0x0000000019930520 (sig) exc->exceptioninformation[1]     = 0x00000000002bf8b0 (object) exc->exceptioninformation[2]     = 0x000000013f9c4210 (throwinfo) exc->exceptioninformation[3]     = 0x000000013f950000 (module)  built-in: _throwinfo, size 28 _throwinfo->attributes           = 0x00000000 [ofs:  0, size: 4, type: unsigned int] _throwinfo->pmfnunwind           = 0x00000000 [ofs:  4, size: 8, type: void (__cdecl*)(void * __ptr64)] _throwinfo->pforwardcompat       = 0x00074230 [ofs: 12, size: 8, type: int (__cdecl*)(void)] _throwinfo->pcatchabletypearray  = 0x00000000 [ofs: 20, size: 8, type: struct _s__catchabletypearray const * __ptr64]  custom: correct::throwinfo, size 16 throwinfo->attributes            = 0x00000000 [ofs:  0, size: 4, type: int] throwinfo->pmfnunwind            = 0x00000000 [ofs:  4, size: 4, type: int] throwinfo->pforwardcompat        = 0x00000000 [ofs:  8, size: 4, type: int] throwinfo->pcatchabletypearray   = 0x00074230 [ofs: 12, size: 4, type: int]  throwinfo->pcatchabletypearray   = 0x0000000000074230 carray                           = 0x000000013f9c4230  built-in: _catchabletype, size 36 _ctype->properties               = 0x00000000 [ofs:  0, size: 4, type: unsigned int] _ctype->ptype                    = 0x00075d58 [ofs:  4, size: 8, type: struct _typedescriptor * __ptr64] _ctype->thisdisplacement.mdisp   = 0xffffffff [ofs: 12, size: 4, type: int] _ctype->thisdisplacement.pdisp   = 0x00000000 [ofs: 16, size: 4, type: int] _ctype->thisdisplacement.vdisp   = 0x00000004 [ofs: 20, size: 4, type: int] _ctype->sizeoroffset             = 0x00000000 [ofs: 24, size: 4, type: int] _ctype->copyfunction             = 0x00000000 [ofs: 28, size: 8, type: void (__cdecl*)(void * __ptr64)]  custom: correct::catchabletype, size 28 ctype->properties                = 0x00000000 [ofs:  0, size: 4, type: int] ctype->ptype                     = 0x00075d58 [ofs:  4, size: 4, type: int] ctype->thisdisplacement.mdisp    = 0x00000000 [ofs:  8, size: 4, type: int] ctype->thisdisplacement.pdisp    = 0xffffffff [ofs: 12, size: 4, type: int] ctype->thisdisplacement.vdisp    = 0x00000000 [ofs: 16, size: 4, type: int] ctype->sizeoroffset              = 0x00000004 [ofs: 20, size: 4, type: int] ctype->copyfunction              = 0x00000000 [ofs: 24, size: 4, type: int]  carray->arrayofcatchabletypes[0] = 0x0000000000074240 ctype                            = 0x000000013f9c4240  ctype->ptype                     = 0x0000000000075d58 type                             = 0x000000013f9c5d58  type->name()                     = "struct `int __cdecl main(void)'::`2'::meow_exception" ctype->sizeoroffset              = 4 

see differences in sizes of whole structures (28 vs 16 bytes, 36 vs 28 bytes), of pointer members (8 vs 4 bytes) , wrong offsets.

when using correct:: definitions, it's easy correct rtti desired.

the original c:\program files (x86)\microsoft visual studio 12.0\vc\crt\src\ehdata.h file msvc 2013 runtime sources contains conditional preprocessor directives #ifdef _eh_relative_offsets substitute pointers __int32 offsets. predefined internal compiler types contains 64-bit wrong pointers.

thus, using internal definitions of rtti structures unreliable in 64-bit mode. 1 should use own definitions pointer members represented 32-bit integers (or #define _eh_relative_offsets , use ehdata.h mentioned above). after that, don't forget manually convert rvas common c++ pointers adding imagebase address usual. one should not trust pointer members in such structures , definitions containing such pointers because they don't reflect true 64-bit binary layout.

i tested msvc 2010, , got same results.

here's code getting correct rtti in 64-bit msvc environment:

#include <stdio.h> #include <typeinfo> #include <stdexcept> #include <windows.h>  //------------------------------------------------------------------------------------------------------------------------------ //! these definitions based on assembly listings produded compiler (/fas) rather built-in ones //! @{  #pragma pack (push, 4)  namespace correct     {      struct catchabletype         {         __int32 properties;         __int32 ptype;         _pmd    thisdisplacement;         __int32 sizeoroffset;         __int32 copyfunction;         };      struct throwinfo         {         __int32 attributes;         __int32 pmfnunwind;         __int32 pforwardcompat;         __int32 pcatchabletypearray;         };      }  #pragma pack (pop)  //! @} //------------------------------------------------------------------------------------------------------------------------------  const unsigned exception_cpp_microsoft                  = 0xe06d7363,  // '?msc'                exception_cpp_microsoft_eh_magic_number1 = 0x19930520,  // '?msc' version magic, see ehdata.h                 exception_output_debug_string            = 0x40010006,  // outputdebugstring() call                exception_thread_name                    = 0x406d1388;  // passing name of thread debugger  void outputdebugprintf (const char* format, ...);  //------------------------------------------------------------------------------------------------------------------------------  long winapi vectoredexceptionhandler (exception_pointers* pointers)     {     const exception_record* exc = pointers->exceptionrecord;      if (exc->exceptioncode == exception_output_debug_string ||         exc->exceptioncode == exception_thread_name)         return exception_continue_search;      outputdebugprintf ("\n%s(): start\n\n", __function__);      outputdebugprintf         ("exc->exceptioncode               = 0x%x\n", exc->exceptioncode);     outputdebugprintf         ("exc->exceptionaddress            = 0x%p\n", exc->exceptionaddress);      if (exc->exceptioninformation[0] == exception_cpp_microsoft_eh_magic_number1 &&          exc->numberparameters >= 3)         {         outputdebugprintf     ("exc->numberparameters            = %u\n", exc->numberparameters);          outputdebugprintf     ("exc->exceptioninformation[0]     = 0x%p (sig)\n",       (void*) exc->exceptioninformation[0]);         outputdebugprintf     ("exc->exceptioninformation[1]     = 0x%p (object)\n",    (void*) exc->exceptioninformation[1]);         outputdebugprintf     ("exc->exceptioninformation[2]     = 0x%p (throwinfo)\n", (void*) exc->exceptioninformation[2]);          if (exc->numberparameters >= 4)             outputdebugprintf ("exc->exceptioninformation[3]     = 0x%p (module)\n",    (void*) exc->exceptioninformation[3]);          outputdebugprintf ("\n");          hmodule module = (exc->numberparameters >= 4)? (hmodule) exc->exceptioninformation[3] : null;          #define rva_to_va_(type, addr)  ( (type) ((uintptr_t) module + (uintptr_t) (addr)) )          const         _throwinfo* _throwinfo = (const         _throwinfo*) exc->exceptioninformation[2];         const correct::throwinfo*  throwinfo = (const correct::throwinfo*) exc->exceptioninformation[2];          #define dump_(var, struc, field)  outputdebugprintf ("%-32s = 0x%08x [ofs: %2u, size: %u, type: %s]\n",  \                                                              #var "->" #field, (var)->field,                 \                                                              offsetof (struc, field), sizeof ((var)->field), \                                                              typeid ((var)->field) .name());         if (_throwinfo)             {             outputdebugprintf ("built-in: _throwinfo, size %u\n", sizeof (_throwinfo));             dump_ (_throwinfo, _throwinfo, attributes);             dump_ (_throwinfo, _throwinfo, pmfnunwind);             dump_ (_throwinfo, _throwinfo, pforwardcompat);             dump_ (_throwinfo, _throwinfo, pcatchabletypearray);             outputdebugprintf ("\n");             }         else             outputdebugprintf ("_throwinfo null\n");          if (throwinfo)             {             outputdebugprintf ("custom: correct::throwinfo, size %u\n", sizeof (correct::throwinfo));             dump_ ( throwinfo, correct::throwinfo, attributes);             dump_ ( throwinfo, correct::throwinfo, pmfnunwind);             dump_ ( throwinfo, correct::throwinfo, pforwardcompat);             dump_ ( throwinfo, correct::throwinfo, pcatchabletypearray);             outputdebugprintf ("\n");             }         else             outputdebugprintf ("throwinfo null\n");          if (throwinfo)             {                           const _catchabletypearray* carray = rva_to_va_(const _catchabletypearray*, throwinfo->pcatchabletypearray);              outputdebugprintf ("throwinfo->pcatchabletypearray   = 0x%p\n",   (void*)(ptrdiff_t) throwinfo->pcatchabletypearray);             outputdebugprintf ("carray                           = 0x%p\n\n", (void*)            carray);              const         _catchabletype* _ctype = rva_to_va_(const         _catchabletype*, carray->arrayofcatchabletypes[0]);             const correct::catchabletype*  ctype = rva_to_va_(const correct::catchabletype*, carray->arrayofcatchabletypes[0]);              outputdebugprintf ("built-in: _catchabletype, size %u\n", sizeof (_catchabletype));             dump_ (_ctype, _catchabletype, properties);             dump_ (_ctype, _catchabletype, ptype);             dump_ (_ctype, _catchabletype, thisdisplacement.mdisp);             dump_ (_ctype, _catchabletype, thisdisplacement.pdisp);             dump_ (_ctype, _catchabletype, thisdisplacement.vdisp);             dump_ (_ctype, _catchabletype, sizeoroffset);             dump_ (_ctype, _catchabletype, copyfunction);             outputdebugprintf ("\n");              outputdebugprintf ("custom: correct::catchabletype, size %u\n", sizeof (correct::catchabletype));             dump_ ( ctype, correct::catchabletype, properties);             dump_ ( ctype, correct::catchabletype, ptype);             dump_ ( ctype, correct::catchabletype, thisdisplacement.mdisp);             dump_ ( ctype, correct::catchabletype, thisdisplacement.pdisp);             dump_ ( ctype, correct::catchabletype, thisdisplacement.vdisp);             dump_ ( ctype, correct::catchabletype, sizeoroffset);             dump_ ( ctype, correct::catchabletype, copyfunction);             outputdebugprintf ("\n");              outputdebugprintf ("carray->arrayofcatchabletypes[0] = 0x%p\n",   (void*) carray->arrayofcatchabletypes[0]);             outputdebugprintf ("ctype                            = 0x%p\n\n", (void*) ctype);              const std::type_info* type = rva_to_va_(const std::type_info*, ctype->ptype);              outputdebugprintf ("ctype->ptype                     = 0x%p\n",   (void*)(ptrdiff_t) ctype->ptype);             outputdebugprintf ("type                             = 0x%p\n\n", (void*)            type);              outputdebugprintf ("type->name()                     = \"%s\"\n", type->name());             outputdebugprintf ("ctype->sizeoroffset              = %u\n\n",   (unsigned) ctype->sizeoroffset);              }          #undef dump_         #undef rva_to_va_         }      outputdebugprintf ("%s(): end\n", __function__);     return exception_continue_search;     }  //------------------------------------------------------------------------------------------------------------------------------  void outputdebugprintf (const char* format, ...)     {     static char buf [1024] = "";      va_list arg; va_start (arg, format);     _vsnprintf_s (buf, sizeof (buf) - 1, _truncate, format, arg);     va_end (arg);      outputdebugstring (buf);     printf ("%s", buf);     }  //------------------------------------------------------------------------------------------------------------------------------  int main()     {         outputdebugprintf ("\ncompiled msvc %d, %d-bit\n", _msc_ver, 8 * sizeof (void*));     outputdebugprintf ("\n%s(): start\n", __function__);      addvectoredexceptionhandler (1, vectoredexceptionhandler);      struct meow_exception { int code; meow_exception() : code (3) {} };      try         {         throw meow_exception();         }      catch (const meow_exception& e)         {         outputdebugprintf ("\n%s(): catch (meow_exception { %d })\n", __function__, e.code);         }      catch (...)         {         outputdebugprintf ("\n%s(): catch (...)\n", __function__);         }      outputdebugprintf ("\n%s(): end\n", __function__);     return 0;     } 

Comments

Popular posts from this blog

mysql - Dreamhost PyCharm Django Python 3 Launching a Site -

java - Sending SMS with SMSLib and Web Services -

java - How to resolve The method toString() in the type Object is not applicable for the arguments (InputStream) -