好库网 好库网首页 | 我的好库
oshjok的专栏

关于 VS2010 异常捕获

发布者:oshjok
发布日期:2013/7/31 11:33:11   更新日期:2013/8/5 17:32:34
阅读次数:3392
评分:4.80
介绍:好长时间没来了,都变了,幸亏帐号还在,密码也好记得。祝 vckbase/okbase 越来越好吧。 记录一下:程序异常崩溃前的信息。
正文:

//=========================================================================.h
#include "DbgHelp.h"  
//调试信息
#pragma comment( lib,"DbgHelp.lib" )private: 
//异常结构体,定义在 WINNT.h 里 
_EXCEPTION_POINTERS * m_epi;
 
//获得异常结构体的解释文本 
CString GetException(_EXCEPTION_POINTERS *epi);
 
//获得一个模块地址的全路径 
CString GetExceptionPath(LPVOID addr);
 
//获得异常信息的参数解释文本 
CString GetExceptionParam(ULONG_PTR* Info,int iCount);
 
//=========================================================================.cpp
// ---------------------------------------------------------------
// 名称: GetException
// 功能: 根据异常结构体,解释出能够识别的文本信息,含中、英文双语信息
// 变量: [in] pei -- 异常信息的结构体
// 返回: 解释后的文本
// 编写: 
// ---------------------------------------------------------------
CString CLogs::GetException(_EXCEPTION_POINTERS *pei){ 
if( NULL==pei )
	return _T("");
 STACKFRAME    sf;
 CONTEXT       ct;
 CString sPath,sInfo,sTemp,sErr_CN,sErr_EN;
 sPath = GetExceptionPath( pei->ExceptionRecord->ExceptionAddress );
 sInfo = GetExceptionParam( pei->ExceptionRecord->ExceptionInformation,pei->ExceptionRecord->NumberParameters );
  
//------------------------------------------------- 
//程序运行到这里,可能已经没有机会获取多国语言资源了 
//所以直接硬编码,采用中、英文双语提示,其他对话框请勿使用这种方式
 CString sep = _T("------------------------------------------------------------------\r\n");
 sErr_CN = sep;
 sErr_EN = sep;
 sTemp.Format( _T("很抱歉,遇到了未知异常,程序需要暂时关闭。\r\n代码: 0x%08X, 标志: 0x%08X, 地址: 0x%08X\r\n")      _T("参数: %d  %s,模块:%s\r\n"),     pei->ExceptionRecord->ExceptionCode,pei->ExceptionRecord->ExceptionFlags,pei->ExceptionRecord->ExceptionAddress,     pei->ExceptionRecord->NumberParameters,sInfo,sPath );
 sErr_CN += sTemp;
 sTemp.Format( _T("Sorry, Dump An unkonw error, need to close program.\r\nCode: 0x%08X, Flag: 0x%08X, Address: 0x%08X\r\n")      _T("Param: %d  %s,Module:%s\r\n"),     pei->ExceptionRecord->ExceptionCode,pei->ExceptionRecord->ExceptionFlags,pei->ExceptionRecord->ExceptionAddress,     pei->ExceptionRecord->NumberParameters,sInfo,sPath );
 sErr_EN += sTemp;
 
//------------------------------------------------- 
	memset( &sf,0,sizeof(STACKFRAME) );
    memcpy( &ct,pei->ContextRecord,sizeof(CONTEXT) );
	sf.AddrPC.Offset    = ct.Eip;
    sf.AddrPC.Mode      = AddrModeFlat;
    sf.AddrStack.Offset = ct.Esp;
    sf.AddrStack.Mode   = AddrModeFlat;
    sf.AddrFrame.Offset = ct.Ebp;
    sf.AddrFrame.Mode   = AddrModeFlat;
    DWORD machineType   = IMAGE_FILE_MACHINE_I386;
    HANDLE hProcess     = GetCurrentProcess();
    HANDLE hThread      = GetCurrentThread();
    SymInitialize( hProcess,NULL,TRUE );
    for( ;; )
	{
		if( !StackWalk( machineType,hProcess,hThread,&sf, &ct,0,SymFunctionTableAccess,SymGetModuleBase,0) )
		{
			break;
        }
		if( sf.AddrFrame.Offset==0 )
		{
			break;
        }
		BYTE symbolBuffer[ sizeof(SYMBOL_INFO) + 1024 ];
        PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer;
        pSymbol->SizeOfStruct = sizeof(symbolBuffer);
        pSymbol->MaxNameLen = 1024;
          
//-------------------------------------------------  
  sTemp.Format( _T("偏移地址:0x%08X\r\n"),sf.AddrPC.Offset);
  sErr_CN += sTemp;
  sTemp.Format( _T("Offset:0x%08X\r\n"),sf.AddrPC.Offset);
  sErr_EN += sTemp;
  
//-------------------------------------------------        
if( SymFromAddr(hProcess,sf.AddrPC.Offset,0,pSymbol) ) {   
#if _UNICODE    
//-------------------------------------------------    
LPCWSTR wstr = AnsiToUnicode( pSymbol->Name );
    sTemp.Format( _T("函数: %s\r\n"),wstr );
       sErr_CN += sTemp;
    sTemp.Format( _T("Function: %s\r\n"),wstr );
      sErr_EN += sTemp;
        delete [] wstr;
    
//-------------------------------------------------   
#else
	sTemp.Format( _T("函数: %s\r\n"),pSymbol->Name );
       sErr_CN += sTemp;
    sTemp.Format( _T("Function: %s\r\n"),pSymbol->Name );
      sErr_EN += sTemp;
#endif
}           
	IMAGEHLP_LINE lineInfo = { sizeof(IMAGEHLP_LINE) };
	DWORD dwLineDisplacement;
	if( SymGetLineFromAddr( hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo ) ) {   
	#if _UNICODE    
//-------------------------------------------------    
LPCWSTR wstr = AnsiToUnicode( lineInfo.FileName );
	sTemp.Format( _T("源文件: %s, 错误行: %u\r\n"), wstr,lineInfo.LineNumber );
    sErr_CN += sTemp;
    sTemp.Format( _T("File: %s, Line: %u\r\n"), wstr,lineInfo.LineNumber );
    sErr_EN += sTemp;
    delete [] wstr;
    
//-------------------------------------------------   
#else    
	sTemp.Format( _T("源文件: %s, 错误行: %u\r\n"), lineInfo.FileName,lineInfo.LineNumber );
    sErr_CN += sTemp;
    sTemp.Format( _T("File: %s, Line: %u\r\n"), lineInfo.FileName,lineInfo.LineNumber );
    sErr_EN += sTemp;
#endif        
   }    
   }    
   SymCleanup( hProcess );
   
//------------------------------------------------- 
 sErr_CN += sep;
 sErr_EN += sep;
 
//------------------------------------------------- 
return (sErr_CN + sErr_EN);
}
// ---------------------------------------------------------------
// 名称: GetExceptionPath
// 功能: 根据异常地址,解释并获得对应的模块全路径
// 变量: [in] addr -- 异常信息的结构体
// 返回: 异常地址对应的模块全路径
// 编写: 
// ---------------------------------------------------------------
CString CLogs::GetExceptionPath(LPVOID addr){
 CString sRet = _T("");
 MEMORY_BASIC_INFORMATION mbi = {0};
 if( FALSE==::VirtualQuery(addr,&mbi,sizeof(mbi)) ) return sRet;
 UINT_PTR hMod = (UINT_PTR)mbi.AllocationBase;
 TCHAR szFilePath[MAX_PATH+1];
 GetModuleFileName( (HMODULE)hMod,szFilePath,MAX_PATH );
 sRet = szFilePath;
 return sRet;
}
// ---------------------------------------------------------------
// 名称: GetExceptionParam
// 功能: 将异常参数信息解释为可识别的文本
// 变量: [in] Info -- 异常信息参数
//   [in] iCount -- 参数的个数
// 返回: 解释后的文本
// 编写: 
// ---------------------------------------------------------------
CString CLogs::GetExceptionParam(ULONG_PTR* Info,int iCount){
	int i = 0;
	CString ss, sRet = _T("");
	for( i=0;i<iCount;i++ ) {    ss.Format( _T("%08X "),Info[i] );
      sRet += ss;
   } return sRet;
} 
//=========================================================================调用
// ---------------------------------------------------------------
// 名称: XDumpException
// 功能: 发生异常时,写入 log/dump 文件,并弹出异常信息对话框
// 变量: [in] epi -- 异常信息的结构体
// 返回: 1,系统异常
// 编写: 
// ---------------------------------------------------------------
LONG WINAPI XDumpException(struct _EXCEPTION_POINTERS* epi){ 
  DWORD dwCode = epi->ExceptionRecord->ExceptionCode;
  if( dwCode==EXCEPTION_ACCESS_VIOLATION ) {  
  //转到这里去处理  
  CLogs log;
  log.Dump( epi );
 }
 return EXCEPTION_EXECUTE_HANDLER;
}
// CGMMainApp 初始化
BOOL CGMMainApp::InitInstance(){ 
//---------------------------------------------------------- 
//异常信息输出,独立运行时有效,VSS 调试环境下无效  
SetUnhandledExceptionFilter( XDumpException );

顺便说一下,这个编辑器不好用哦,光标不随鼠标点击走,用上下键,很费劲的。我是WIN7+IE10,其他童鞋是不是也有这种情况?

 

 


评论 [发表评论]
  • 我晕~ 格式怎么变成这样了?

    发布者

    2013/7/31 11:33:58


  • 更多评论
账号 密码 还没帐号呢,现在注册一个?

免责声明:好库网所展示的信息由买卖双方自行提供,其真实性、准确性和合法性由信息发布人负责。好库网不提供任何保证,并不承担任何法律责任。