首先在程序进入点前加上如下代码:#include <DbgHelp.h>
#include <vector> #include <string> #pragma comment( lib,"dbghelp.lib" ) using namespace std; const int MAX_ADDRESS_LENGTH = 32; const int MAX_NAME_LENGTH = 1024; struct CrashInfo { CHAR ErrorCode[MAX_ADDRESS_LENGTH]; CHAR Address[MAX_ADDRESS_LENGTH]; CHAR Flags[MAX_ADDRESS_LENGTH]; }; struct CallStackInfo { CHAR ModuleName[MAX_NAME_LENGTH]; CHAR MethodName[MAX_NAME_LENGTH]; CHAR FileName[MAX_NAME_LENGTH]; CHAR LineNumber[MAX_NAME_LENGTH]; }; void SaftStrCpy( char* szDast,size_t nMaxDestSize,const char* szSrc ) { if ( nMaxDestSize <= 0 ) { return; } if ( strlen( szSrc ) < nMaxDestSize ) { strcpy( szDast,szSrc ); } else { strncpy( szDast,szSrc,nMaxDestSize ); szDast[nMaxDestSize-1] = '\0'; } } CrashInfo GetCrashInfo( const EXCEPTION_RECORD* pRecord ) { CrashInfo crashInfo; SaftStrCpy( crashInfo.Address,MAX_ADDRESS_LENGTH,"N/A" ); SaftStrCpy( crashInfo.ErrorCode,MAX_ADDRESS_LENGTH,"N/A" ); SaftStrCpy( crashInfo.Flags,MAX_ADDRESS_LENGTH,"N/A" ); sprintf( crashInfo.Address, "%08X", pRecord->ExceptionAddress); sprintf( crashInfo.ErrorCode, "%08X", pRecord->ExceptionCode); sprintf( crashInfo.Flags, "%08X", pRecord->ExceptionFlags); return crashInfo; } // 得到CallStack信息 // vector<CallStackInfo> GetCallStack(const CONTEXT *pContext) { HANDLE hProcess = GetCurrentProcess(); SymInitialize(hProcess, NULL, TRUE); vector<CallStackInfo> arrCallStackInfo; CONTEXT c = *pContext; STACKFRAME64 sf; memset(&sf, 0, sizeof(STACKFRAME64)); DWORD dwImageType = IMAGE_FILE_MACHINE_I386; // 不同的CPU类型,具体信息可查询MSDN // #ifdef _M_IX86 sf.AddrPC.Offset = c.Eip; sf.AddrPC.Mode = AddrModeFlat; sf.AddrStack.Offset = c.Esp; sf.AddrStack.Mode = AddrModeFlat; sf.AddrFrame.Offset = c.Ebp; sf.AddrFrame.Mode = AddrModeFlat; #elif _M_X64 dwImageType = IMAGE_FILE_MACHINE_AMD64; sf.AddrPC.Offset = c.Rip; sf.AddrPC.Mode = AddrModeFlat; sf.AddrFrame.Offset = c.Rsp; sf.AddrFrame.Mode = AddrModeFlat; sf.AddrStack.Offset = c.Rsp; sf.AddrStack.Mode = AddrModeFlat; #elif _M_IA64 dwImageType = IMAGE_FILE_MACHINE_IA64; sf.AddrPC.Offset = c.StIIP; sf.AddrPC.Mode = AddrModeFlat; sf.AddrFrame.Offset = c.IntSp; sf.AddrFrame.Mode = AddrModeFlat; sf.AddrBStore.Offset = c.RsBSP; sf.AddrBStore.Mode = AddrModeFlat; sf.AddrStack.Offset = c.IntSp; sf.AddrStack.Mode = AddrModeFlat; #else #error "Platform not supported!" #endif HANDLE hThread = GetCurrentThread(); while (true) { // 该函数是实现这个功能的最重要的一个函数 // 函数的用法以及参数和返回值的具体解释可以查询MSDN // if (!StackWalk64(dwImageType, hProcess, hThread, &sf, &c, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) { break; } if (sf.AddrFrame.Offset == 0) { break; } CallStackInfo callstackinfo; SaftStrCpy(callstackinfo.MethodName, MAX_NAME_LENGTH, "N/A"); SaftStrCpy(callstackinfo.FileName, MAX_NAME_LENGTH, "N/A"); SaftStrCpy(callstackinfo.ModuleName, MAX_NAME_LENGTH, "N/A"); SaftStrCpy(callstackinfo.LineNumber, MAX_NAME_LENGTH, "N/A"); BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL64) + MAX_NAME_LENGTH]; IMAGEHLP_SYMBOL64 *pSymbol = (IMAGEHLP_SYMBOL64*)symbolBuffer; memset(pSymbol, 0, sizeof(IMAGEHLP_SYMBOL64) + MAX_NAME_LENGTH); pSymbol->SizeOfStruct = sizeof(symbolBuffer); pSymbol->MaxNameLength = MAX_NAME_LENGTH; DWORD symDisplacement = 0; // 得到函数名 // if (SymGetSymFromAddr64(hProcess, sf.AddrPC.Offset, NULL, pSymbol)) { SaftStrCpy(callstackinfo.MethodName, MAX_NAME_LENGTH, pSymbol->Name); } IMAGEHLP_LINE64 lineInfo; memset(&lineInfo, 0, sizeof(IMAGEHLP_LINE64)); lineInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64); DWORD dwLineDisplacement; // 得到文件名和所在的代码行 // if (SymGetLineFromAddr64(hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo)) { SaftStrCpy(callstackinfo.FileName, MAX_NAME_LENGTH, lineInfo.FileName); sprintf(callstackinfo.LineNumber, "%d", lineInfo.LineNumber); } IMAGEHLP_MODULE64 moduleInfo; memset(&moduleInfo, 0, sizeof(IMAGEHLP_MODULE64)); moduleInfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64); // 得到模块名 // if (SymGetModuleInfo64(hProcess, sf.AddrPC.Offset, &moduleInfo)) { SaftStrCpy(callstackinfo.ModuleName, MAX_NAME_LENGTH, moduleInfo.ModuleName); } arrCallStackInfo.push_back(callstackinfo); } SymCleanup(hProcess); return arrCallStackInfo; } // 处理Unhandled Exception的回调函数 // LONG ApplicationCrashHandler(EXCEPTION_POINTERS *pException) { // 确保有足够的栈空间 // #ifdef _M_IX86 if (pException->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) { static char TempStack[1024 * 128]; __asm mov eax,offset TempStack[1024 * 128]; __asm mov esp,eax; } #endif CrashInfo crashinfo = GetCrashInfo(pException->ExceptionRecord); // 输出Crash信息 // CFile file( "a.txt",CFile::modeReadWrite|CFile::modeCreate ); CString strFormat; strFormat.Format( "ErrorCode: %s\r\nAddress: %s\r\nFlags: %s\r\n",crashinfo.ErrorCode,crashinfo.Address,crashinfo.Flags ); // strFormat.Format( "ErrorCode: %s",crashinfo.ErrorCode ); // strFormat.Format( "\r\n"); file.Write( strFormat.GetBuffer( 0 ),strFormat.GetLength() ); vector<CallStackInfo> arrCallStackInfo = GetCallStack(pException->ContextRecord); // 输出CallStack // file.Write( _T("调用堆栈:\r\n"),sizeof( "调用堆栈:\r\n" ) ); for (vector<CallStackInfo>::iterator i = arrCallStackInfo.begin(); i != arrCallStackInfo.end(); ++i) { CallStackInfo callstackinfo = (*i); strFormat.Format( "%s() : [%s] (File: %s @Line %s)\r\n",callstackinfo.MethodName,callstackinfo.ModuleName, callstackinfo.FileName,callstackinfo.LineNumber ); file.Write( strFormat.GetBuffer( 0 ),strFormat.GetLength() ); } // 这里弹出一个错误对话框并退出程序 // FatalAppExit(-1, "程序出现了异常,请重新启动程序..." ); return EXCEPTION_EXECUTE_HANDLER; }然后再真正执行的地方使用如下函数即可:
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);
这样,程序在core掉的时候会把core的那个点的堆栈信息打印出来.存到a.txt文件下.