Minidump文件生成
1、Minidump概念
minidump(小存储器转储)可以理解为一个dump文件,里面记录了能够帮助调试crash的最小有用信息。实际上,如果你在系统属性 -> 高级 -> 启动和故障恢复 -> 设置 -> 写入调试信息中选择“小内存转储(64 KB)”的话,当系统意外停止时都会在C:\Windows\Minidump\路径下生成一个.dmp后缀的文件,这个文件就是minidump文件,只不过这个是内核态的minidump。
我们要生成的是用户态的minidump,文件中包含了程序运行的模块信息、线程信息、堆栈调用信息等。而且为了符合其mini的特性,dump文件是压缩过的。
2、生成minidump文件
通过drwtsn32、NTSD、CDB等调试工具生成Dump文件, drwtsn32存在的缺点虽然NTSD、CDB可以完全解决,但并不是所有的操作系统中都安装了NTSD、CDB等调试工具。根据MiniDumpWriteDump接口,完全可以程序自动生成Dump文件。
3、 自动生成Minidump文件
当程序遇到未处理异常(主要指非指针造成)导致程序崩溃死,如果在异常发生之前调用了SetUnhandledExceptionFilter()函数,异常交给函数处理。因而,在程序开始处增加SetUnhandledExceptionFilter()函数,并在函数中利用适当的方法生成Dump文件,即可实现需要的功能。
1、开启生成Dump文件
void RunCrashHandler()
{
// 设置产生奔溃dump文件功能 // WINAPI
SetUnhandledExceptionFilter(UnhandledExceptionFilterEx); // 添加回调
PreventSetUnhandledExceptionFilter();
}
SetUnhandledExceptionFilter() 这个函数的返回值有三种情况:
EXCEPTION_EXECUTE_HANDLER equ 1 表示我已经处理了异常,可以优雅地结束了
EXCEPTION_CONTINUE_SEARCH equ 0 表示我不处理,于是windows调用默认的处理程序显示一个错误框,并结束
EXCEPTION_CONTINUE_EXECUTION equ -1 表示错误已经被修复,请从异常发生处继续执行
2、指定dump文件名称等
void UnhandledExceptionFilterExImpl(struct _EXCEPTION_POINTERS *pException)
{
// 日志按日期存储
SYSTEMTIME tmCurrent;
GetLocalTime(&tmCurrent);
TCHAR szDumpFilePath[MAX_PATH] = { 0 };
GetModuleFileName(0, szDumpFilePath, MAX_PATH);
PTSTR pszTemp = _tcsrchr(szDumpFilePath, _T('\\'));
if (pszTemp) {
StringCchCopy(szLogFilePath, SIZE_ARRAY(szDumpFilePath), pszTemp + 1);
pszTemp[1] = 0;
} else {
StringCchCopy(szLogFilePath, SIZE_ARRAY(szLogFilePath), _T("Exception"));
}
TCHAR szDMPFileName[MAX_PATH];
StringCchPrintf(szDMPFileName, MAX_PATH, _T("%s-%02d-%02d-%02d.dmp"), szDumpFilePath, tmCurrent.wHour, tmCurrent.wMinute, tmCurrent.wSecond);
CreateDumpFile(szDMPFileName, pException);
}
3、生成dump文件
void CreateDumpFile(LPCTSTR lpstrDumpFilePathName, EXCEPTION_POINTERS *pException)
{
// 创建Dump文件
HANDLE hDumpFile = CreateFile(lpstrDumpFilePathName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE != hDumpFile)
{
// Dump信息
MINIDUMP_EXCEPTION_INFORMATION ExInfo;
if (pException)
{
ExInfo.ThreadId = ::GetCurrentThreadId();
ExInfo.ExceptionPointers = pException;
ExInfo.ClientPointers = TRUE;
}
// 写入Dump文件内容 // DbgHelp库函数
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpWithFullMemory, pException ? &ExInfo : NULL, NULL, NULL);
CloseHandle(hDumpFile);
}
}
BOOL PreventSetUnhandledExceptionFilter()
{
HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
if (hKernel32 == NULL)
return FALSE;
void *pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter");
if(pOrgEntry == NULL)
return FALSE;
unsigned char newJump[ 100 ];
DWORD dwOrgEntryAddr = (DWORD) pOrgEntry;
dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far
void *pNewFunc = &MyDummySetUnhandledExceptionFilter;
DWORD dwNewEntryAddr = (DWORD) pNewFunc;
DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr;
newJump[ 0 ] = 0xE9; // JMP absolute
memcpy_s(&newJump[ 1 ], sizeof(newJump) - 1, &dwRelativeAddr, sizeof(pNewFunc));
SIZE_T bytesWritten;
BOOL bRet = WriteProcessMemory(GetCurrentProcess(), pOrgEntry, newJump, sizeof(pNewFunc) + 1, &bytesWritten);
::FreeLibrary(hKernel32);
return bRet;
}
win7自动生成dump-----------------------------------------------------------------------------------------------------------------------------------------------------------------
win7下需打开regedit--> 找到:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting]
在它下面加一项LocalDumps,并做如下项配置:
Value | 描述 | Type | 默认值 |
DumpFolder | 文件保存路径 | REG_EXPAND_SZ | %LOCALAPPDATA%CrashDumps |
DumpCount | dump文件的最大数目 | REG_DWORD | 10 |
DumpType | 指定生成的dump类型: 0:Custom dump 1:Mini dump 2:Full dump | REG_DWORD | 1 |
CustomDumpFlags | 仅在DumpType为0时使用 为MINIDUMP_TYPE的组合 | REG_DWORD | |
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps"
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps" /v DumpFolder /t REG_EXPAND_SZ /d "C:\MyDump" /f
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps" /v DumpType /t REG_DWORD /d 2 /f
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps" /v DumpCount /t REG_DWORD /d 10 /f