条件:需要pdb调试符号文件
可以使用seh将程序入口包围起来,一旦出现异常,就在异常处理器中,查询其pdb符号文件
输出异常的代码行以及堆栈,这对日常调试跟踪问题,很有益处
int __cdecl PrintExceptionHandler(PEXCEPTION_POINTERS pExp, LPCSTR Message)
{
memset(bufferIMAGEHLP_SYMBOL,0,10240);
DWORD nameBytes = sizeof(bufferIMAGEHLP_SYMBOL) - sizeof(SYMBOL_INFO)+sizeof(TCHAR);
PSYMBOL_INFO symbol = reinterpret_cast<PSYMBOL_INFO>(bufferIMAGEHLP_SYMBOL);
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
symbol->MaxNameLen = nameBytes/(sizeof(TCHAR));//The length of the name, in characters,not bytes
STACKFRAME64 sratckFrame = {0};
sratckFrame.AddrPC.Offset = pExp->ContextRecord->Eip;
sratckFrame.AddrStack.Offset = pExp->ContextRecord->Esp;
sratckFrame.AddrFrame.Offset = pExp->ContextRecord->Ebp;
sratckFrame.AddrPC.Mode = AddrModeFlat;
sratckFrame.AddrStack.Mode = AddrModeFlat;
sratckFrame.AddrFrame.Mode = AddrModeFlat;
DBGVIEW("%s Occurred a Exception:",Message);
if(!::SymInitialize(::GetCurrentProcess(), NULL, TRUE))
{
DBGVIEW("CAN NOT FIND PDB FILE,CAN NOT OUTPUT CALLSTACK WITH LINE AND FUNC NAME");
return FALSE;
}
int stackLevel = 0;
BOOL bResult = FALSE;
DWORD levelFound = 0;
const char* levelstr = " LEVEL:";
const char* linestr = " LINE:";
const char* filestr = " FILE:";
const char* funcstr = " FUNC:";
for(;;)
{
bResult = ::StackWalk64(IMAGE_FILE_MACHINE_I386,
::GetCurrentProcess(),
::GetCurrentThread(),
&sratckFrame,
NULL,
NULL,
SymFunctionTableAccess64,
SymGetModuleBase64,
NULL);
if(!bResult || sratckFrame.AddrFrame.Offset == 0) {
break;
}
DWORD64 displacement;
BOOL bResult2 = FALSE;
memset(symbol->Name,0,nameBytes);//SymFromAddr can not reset Name
bResult = ::SymFromAddr(GetCurrentProcess(), sratckFrame.AddrPC.Offset, &displacement, symbol);
if(bResult)
{
DWORD displacement2 = 0;
IMAGEHLP_LINE64* imageHelpLine = (IMAGEHLP_LINE64*)bufferIMAGE_LINE;
memset(bufferIMAGE_LINE,0,sizeof(IMAGEHLP_LINE64)+MAX_PATH*2);
imageHelpLine->SizeOfStruct = sizeof(IMAGEHLP_LINE64);
imageHelpLine->FileName = (CHAR*)(imageHelpLine+1);
bResult2 = ::SymGetLineFromAddr64(::GetCurrentProcess(),sratckFrame.AddrPC.Offset, &displacement2,imageHelpLine);
if(bResult2)
{
if(levelFound==0)
{
DBGVIEW(" STACK: LINE: FILE\\FUNCTION()");
}
DBGVIEW(" %02d:%05d : %s\\%s()",stackLevel,imageHelpLine->LineNumber,
imageHelpLine->FileName,symbol->Name);
levelFound++;
}
}
stackLevel++;
}
if(levelFound<=0)
{
DBGVIEW("CAN NOT FIND PDB FILE,CAN NOT OUTPUT CALLSTACK WITH LINE AND FUNC NAME");
}
::SymCleanup(::GetCurrentProcess());
return TRUE;
}
还提供方便使用的宏
#define DBGTRY __try{
#define DBGEXCEPT }__except(PrintExceptionHandler(GetExceptionInformation(),__FILE__)){\
DBGVIEW("File:%s at Line:%s has a exception",__FILE__,__LINE__);}
只需要用DBGTRY和DBGEXCEPT将可能出错的代码包围起来,即可
注意,使用该宏的函数,不能有栈上的类的变量