异常时输出异常来源

条件:需要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将可能出错的代码包围起来,即可

注意,使用该宏的函数,不能有栈上的类的变量

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值