(1)把dmp,PDB文件,放在exe同一目录下(PDB文件必须是与exe同时编译生成的)
(2)代码回滚到编译exe时的版本
(3)双击dmp文件,或把dmp文件拖动到Visual studio窗口
(4)点击仅限本机进行调试
(5)然后可以查看调用堆栈等分析操作
【提示】如果查找堆栈提示找不到源码,可以右键项目“属性”-》“调试源文件”,设置源码根路径
二 生成dmp
(1)使用任务管理器生成
tab栏“进程”-》右键”创建转存文件”
(2)C++代码中,使用DbgHelp模块的MINIDUMP编程生成
#include "DbgHelp.h" typedef BOOL (WINAPI* MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType, CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam); long CSE_Exception::_DbgDumpError(struct _EXCEPTION_POINTERS *excpInfo, LPCTSTR szPrex ) { LONG retval = EXCEPTION_CONTINUE_SEARCH; HMODULE hDll = ::LoadLibrary(_T("DBGHELP.DLL")); LPCTSTR szResult = NULL; MINIDUMPWRITEDUMP pDump = NULL; if (hDll) pDump = (MINIDUMPWRITEDUMP)::GetProcAddress(hDll,"MiniDumpWriteDump"); if (pDump) { TCHAR szDumpPath [_MAX_PATH] = {0}; TCHAR szDumpFile [_MAX_PATH] = {0}; GetModuleFileName(NULL, szDumpPath, _MAX_PATH); _tcsrchr(szDumpPath, _T('\\'))[1] = 0; _tcscat(szDumpPath, _T("..\\logs\")); time_t timeCurrent = time(0); struct tm* tmc = localtime(&timeCurrent); if ( tmc ) _stprintf(szDumpFile, _T("%s%d_%d_%d_%d_%d.dmp"), szPrex, tmc->tm_mon+1, tmc->tm_mday, tmc->tm_hour, tmc->tm_min, tmc->tm_sec); else _tcscpy(szDumpFile, _T("error.dmp")); _tcscat(szDumpPath, szDumpFile); // create the file HANDLE hFile = ::CreateFile( szDumpPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (hFile!=INVALID_HANDLE_VALUE) { if (excpInfo == NULL) //如果没有传入异常, 比如是在程序里面调用的, 生成一个异常 { // Generate exception to get proper context in dump DWORD dwSize = 0; char *sz = "_EXCEPTION_POINTERS is null"; ::WriteFile(hFile, sz, strlen(sz), &dwSize, NULL); } else { MINIDUMP_EXCEPTION_INFORMATION eInfo; eInfo.ThreadId = GetCurrentThreadId(); //把需要的信息添进去 eInfo.ExceptionPointers = excpInfo; eInfo.ClientPointers = FALSE; // Dump的类型是小型的, 节省空间. 可以参考MSDN生成更详细的Dump. pDump( GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, excpInfo ? &eInfo : NULL, NULL, NULL); } ::CloseHandle(hFile); } } if( hDll ) ::FreeLibrary(hDll); return retval; } void CSE_Exception::InitSEException() { _set_se_translator( CSE_Exception::trans_func ); } void CSE_Exception::_DumpCallStack() { __try { __try { RaiseException(1, 0, 0, NULL); } __finally { } } __except(_DbgDumpError(GetExceptionInformation(), _T("T")), EXCEPTION_CONTINUE_EXECUTION) { } } void CSE_Exception::trans_func( unsigned int uSENum, _EXCEPTION_POINTERS* pExp ) { #define SE_BUF_SIZE 250 TCHAR pszBuf[SE_BUF_SIZE+2]; _DbgDumpError(pExp, _T("e")); switch(uSENum) { case EXCEPTION_ACCESS_VIOLATION: _sntprintf(pszBuf, SE_BUF_SIZE, _T("Access Violation: IP: 0xX %s Address: 0xX"), pExp->ExceptionRecord->ExceptionAddress, pExp->ExceptionRecord->ExceptionInformation[0]?_T("Write"):_T("Read"), pExp->ExceptionRecord->ExceptionInformation[1]); break; case EXCEPTION_INT_DIVIDE_BY_ZERO: _sntprintf(pszBuf, SE_BUF_SIZE, _T("INT_DIVIDE_BY_ZERO")); break; case EXCEPTION_FLT_DIVIDE_BY_ZERO: _sntprintf(pszBuf, SE_BUF_SIZE, _T("FLT_DIVIDE_BY_ZERO")); break; case EXCEPTION_ILLEGAL_INSTRUCTION: _sntprintf(pszBuf, SE_BUF_SIZE, _T("ILLEGAL_INSTRUCTION")); break; case EXCEPTION_PRIV_INSTRUCTION: _sntprintf(pszBuf, SE_BUF_SIZE, _T("EXCEPTION_PRIV_INSTRUCTION")); break; case EXCEPTION_STACK_OVERFLOW: _sntprintf(pszBuf, SE_BUF_SIZE, _T("EXCEPTION_STACK_OVERFLOW")); break; default: _sntprintf(pszBuf, SE_BUF_SIZE, _T("Unknown SE_exception: X"), uSENum); break; } CSE_Exception e(pszBuf); e.m_nSENumber = uSENum; e.m_SERecord = *(pExp->ExceptionRecord); e.m_SEContext = *(pExp->ContextRecord); throw e; } 然后在程序的InitInstance中加入代码如下: LONG WINAPI DbgUnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo) { CSE_Exception::_DbgDumpError(pExceptionInfo, _T("E")); return EXCEPTION_CONTINUE_SEARCH; // 程序停止运行 } BOOL CDCPWorkerApp::InitInstance() { //EHA CSE_Exception::InitSEException(); //捕获未处理的异常 SetUnhandledExceptionFilter(DbgUnhandledExceptionFilter); }
三 常见错误码含义
(1)0xC0000005 内存越界、野指针、重复释放指针等;
(0xBCD20000 处有未经处理的异常(在 MPR-FAST-5080-20160928115806.dmp 中): 0xC0000005: 执行位置 0xBCD20000 时发生访问冲突。)