程序崩溃时生成崩溃报告
关键词:SetUnhandledExceptionFilter MiniDumpWriteDump
1、声明:该流程只对本线程有效,如果是多线程,需要对每个线程都做调用处理。
2、代码流程:
typedef BOOL (*MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, PMINIDUMP_CALLBACK_INFORMATION CallbackParam); MINIDUMPWRITEDUMP g_pDumpFunc = NULL; // 声明函数指针 // 参数lpExceptionInfo包含了异常信息,由系统提供 LONG WINAPI ExceptionFilterFunc (struct _EXCEPTION_POINTERS *lpExceptionInfo) { LONG ret = EXCEPTION_CONTINUE_SEARCH; // 根据当前时间创建dmp空文件 CString strFile; CTime timeNow = CTime::GetCurrentTime(); strFile = timeNow.Format("%Y%m%d%H%M%S"); strFile += ".dmp"; ::CreateDirectory("dumps\\",NULL); strFile = "dumps\\" + strFile; HANDLE hFile = ::CreateFile(strFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL ); if (hFile != INVALID_HANDLE_VALUE) { MINIDUMP_EXCEPTION_INFORMATION ExInfo; ExInfo.ThreadId = ::GetCurrentThreadId(); ExInfo.ExceptionPointers = lpExceptionInfo; ExInfo.ClientPointers = NULL; // 将崩溃信息记录到dmp文件中 BOOL bRet = g_pDumpFunc( GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL ); if (bRet) ret = EXCEPTION_EXECUTE_HANDLER; else { AfxMessageBox("call MiniDumpWriteDump fail..."); } ::CloseHandle(hFile); } return ret; } // thread function UINT xxThread(LPVOID pParam) { // load dgbhelp.dll HMODULE hDll = NULL; hDll = LoadLibrary("dbghelp.dll") ; if (hDll == NULL) { AfxMessageBox("load dbghelp.dll fail"); return FALSE; } // load MiniDumpWriteDump function g_pDumpFunc = (MINIDUMPWRITEDUMP)::GetProcAddress(hDll, "MiniDumpWriteDump"); if (g_pDumpFunc == NULL) { AfxMessageBox("load MiniDumpWriteDump function fail"); return FALSE; } // 设置异常捕获函数 ::SetUnhandledExceptionFilter(ExceptionFilterFunc); return TRUE; }
3、采用这种方法,基本上可以在程序崩溃的时候收集到崩溃报告并生成dmp文件,如果没有dmp文件生成,那么可能发生了栈溢出、覆盖的情况,请检查代码是否存在栈溢出、覆盖的情况。
4、如果收集到的dmp文件是空的,这种情况我碰到过,根据我自己的经验,原因是内存耗尽了。