- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在研究小型 Windows 异常处理引擎,试图从系统中收集最多的信息,包括 C++ 异常 RTTI。
在 MSVS 2015 编译的 32 位 VectoredExceptionHandler 中,我成功地获得了指向所抛出类型的 RTTI 的 std::type_info 指针。它可以很容易地在 ((_ThrowInfo*) ExceptionPointers->ExceptionRecord->ExceptionInformation[2])->pCatchableTypeArray->arrayOfCatchableTypes[0]
中找到(参见 classic article of Raymond Chen ,MS 的 ehdata.h
文件和许多其他文件中的一些定义)。该方法基于获取pCatchableTypeArray
MSVC 内置成员 _ThrowInfo
由编译器构建的结构数据。
但是在64位环境下,_ThrowInfo
不包含直接的 RTTI:不幸的是,pCatchableTypeArray
一片空白。在反汇编窗口中,我看到即使在调用 _CxxThrowException
之前它也是 NULL , 主要 MS throw 处理程序。我搜索了许多关于 MSVC 中使用的新 64 位异常处理机制的文章,但没有关于 RTTI 的信息。但也许我错过了一些东西。
是否有任何方法可以获得在 64 位 MSVC 环境中工作的 vector 异常处理程序中抛出的 C++ 异常的 std::type_info(或简单的类型名称)?
这是转储 32 位和 64 位异常信息的输出:
32 位(RTTI 成功):
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 })
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 })
#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 to the 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;
}
// 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
最佳答案
为了解决这个问题,我深入研究并发现了一些关于 MSVC 64 位模式的有趣的事情。我发现我们不能依赖 64 位模式下的内部编译器预定义类型,因为其中一些是错误的。
我对比了一些编译器预定义的内部结构的定义,比如_ThrowInfo
和 _CatchableType
, 编译器生成的程序集列表正在运行 /FAs
命令行开关。
以下是从程序集文件中提取的这些结构的实例(以下是 MSVC 2015 64 位版本):
;---------------------------------------------------------------------------------------
; Listing generated by Microsoft Optimizing Compiler Version 19.00.24213.1
; Simplified: many lines skipped, some 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
;---------------------------------------------------------------------------------------
FLAT
修饰符代替了
imagerel
,
DD
中的
DQ
代替了
_TypeDescriptor
)。
ehdata.h
的预定义类型进行比较。文件(例如,参见 MSVC 2013 中的
well-known source by Geoff Chappell 或
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\crt\src\ehdata.h
文件;不幸的是,该文件在 MSVC 2015 运行时源中不存在):
typedef const struct _s__ThrowInfo
{
unsigned int attributes;
_PMFN pmfnUnwind; // this is a pointer!
int (__cdecl *pForwardCompat) (...); // this is a pointer too!
_CatchableTypeArray *pCatchableTypeArray; // this is a pointer too!
}
_ThrowInfo;
typedef const struct _s__CatchableType
{
unsigned int properties;
_TypeDescriptor *pType; // this is a pointer too!
_PMD thisDisplacement;
int sizeOrOffset;
_PMFN copyFunction; // this is a pointer too!
}
_CatchableType;
imagerel
地址修饰符,这些是指 RVA。
这些 RVA 是 32 位的 并定义为 32 位
DD
关键词。
_ThrowInfo
或
_CatchableType
上面)
不对应于汇编器二进制布局。 从 C++ 端看,这些结构的大小更大,而且字段偏移量也是错误的。
namespace CORRECT
{
struct ThrowInfo
{
__int32 attributes;
__int32 pmfnUnwind; // now this is 32-bit RVA
__int32 pForwardCompat; // now this is 32-bit RVA
__int32 pCatchableTypeArray; // now this is 32-bit RVA
};
struct CatchableType
{
__int32 properties;
__int32 pType; // now this is 32-bit RVA
_PMD thisDisplacement;
__int32 sizeOrOffset;
__int32 copyFunction; // now this is 32-bit RVA
};
}
_ThrowInfo
的内容和
_CatchableType
使用内部定义和我自己的定义。结果如下(MSVC 2015 64 位):
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
CORRECT::
定义,很容易获得所需的正确 RTTI。
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\crt\src\ehdata.h
来自 MSVC 2013 运行时源的文件包含条件预处理器指令
#ifdef _EH_RELATIVE_OFFSETS
替换指向
__int32
的指针抵消。但是预定义的内部编译器类型总是包含 64 位错误的指针。
#define _EH_RELATIVE_OFFSETS
并使用上述
ehdata.h
)。之后,不要忘记通过添加
ImageBase
手动将 RVA 转换为通用 C++ 指针。地址照常。但是
不应信任此类结构中的指针成员 以及包含此类指针的定义,因为
它们不反射(reflect)真正的 64 位二进制布局。
#include <stdio.h>
#include <typeinfo>
#include <stdexcept>
#include <windows.h>
//------------------------------------------------------------------------------------------------------------------------------
//! These definitions are based on assembly listings produded by the compiler (/FAs) rather than 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 to the 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 is 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 is 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 with 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;
}
关于Windows 64 位 VectoredExceptionHandler 中的 C++ RTTI,MS Visual Studio 2015,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39113168/
我想做的是让 JTextPane 在 JPanel 中占用尽可能多的空间。对于我使用的 UpdateInfoPanel: public class UpdateInfoPanel extends JP
我在 JPanel 中有一个 JTextArea,我想将其与 JScrollPane 一起使用。我正在使用 GridBagLayout。当我运行它时,框架似乎为 JScrollPane 腾出了空间,但
我想在 xcode 中实现以下功能。 我有一个 View Controller 。在这个 UIViewController 中,我有一个 UITabBar。它们下面是一个 UIView。将 UITab
有谁知道Firebird 2.5有没有类似于SQL中“STUFF”函数的功能? 我有一个包含父用户记录的表,另一个表包含与父相关的子用户记录。我希望能够提取用户拥有的“ROLES”的逗号分隔字符串,而
我想使用 JSON 作为 mirth channel 的输入和输出,例如详细信息保存在数据库中或创建 HL7 消息。 简而言之,输入为 JSON 解析它并输出为任何格式。 最佳答案 var objec
通常我会使用 R 并执行 merge.by,但这个文件似乎太大了,部门中的任何一台计算机都无法处理它! (任何从事遗传学工作的人的附加信息)本质上,插补似乎删除了 snp ID 的 rs 数字,我只剩
我有一个以前可能被问过的问题,但我很难找到正确的描述。我希望有人能帮助我。 在下面的代码中,我设置了varprice,我想添加javascript变量accu_id以通过rails在我的数据库中查找记
我有一个简单的 SVG 文件,在 Firefox 中可以正常查看 - 它的一些包装文本使用 foreignObject 包含一些 HTML - 文本包装在 div 中:
所以我正在为学校编写一个 Ruby 程序,如果某个值是 1 或 3,则将 bool 值更改为 true,如果是 0 或 2,则更改为 false。由于我有 Java 背景,所以我认为这段代码应该有效:
我做了什么: 我在这些账户之间创建了 VPC 对等连接 互联网网关也连接到每个 VPC 还配置了路由表(以允许来自双方的流量) 情况1: 当这两个 VPC 在同一个账户中时,我成功测试了从另一个 La
我有一个名为 contacts 的表: user_id contact_id 10294 10295 10294 10293 10293 10294 102
我正在使用 Magento 中的新模板。为避免重复代码,我想为每个产品预览使用相同的子模板。 特别是我做了这样一个展示: $products = Mage::getModel('catalog/pro
“for”是否总是检查协议(protocol)中定义的每个函数中第一个参数的类型? 编辑(改写): 当协议(protocol)方法只有一个参数时,根据该单个参数的类型(直接或任意)找到实现。当协议(p
我想从我的 PHP 代码中调用 JavaScript 函数。我通过使用以下方法实现了这一点: echo ' drawChart($id); '; 这工作正常,但我想从我的 PHP 代码中获取数据,我使
这个问题已经有答案了: Event binding on dynamically created elements? (23 个回答) 已关闭 5 年前。 我有一个动态表单,我想在其中附加一些其他 h
我正在尝试找到一种解决方案,以在 componentDidMount 中的映射项上使用 setState。 我正在使用 GraphQL连同 Gatsby返回许多 data 项目,但要求在特定的 pat
我在 ScrollView 中有一个 View 。只要用户按住该 View ,我想每 80 毫秒调用一次方法。这是我已经实现的: final Runnable vibrate = new Runnab
我用 jni 开发了一个 android 应用程序。我在 GetStringUTFChars 的 dvmDecodeIndirectRef 中得到了一个 dvmabort。我只中止了一次。 为什么会这
当我到达我的 Activity 时,我调用 FragmentPagerAdapter 来处理我的不同选项卡。在我的一个选项卡中,我想显示一个 RecyclerView,但他从未出现过,有了断点,我看到
当我按下 Activity 中的按钮时,会弹出一个 DialogFragment。在对话框 fragment 中,有一个看起来像普通 ListView 的 RecyclerView。 我想要的行为是当
我是一名优秀的程序员,十分优秀!