Windows下C++编程生成minidump文件

生成minidump目的是保存程序异常时的调用栈信息,便于寻找问题原因。

1, 添加下面得函数,

#include <dbghelp.h>
#include <shellapi.h>
#include <shlobj.h>

LONG WINAPI GenerateDump(struct _EXCEPTION_POINTERS *pExceptionPointers)
{
LONG ret = EXCEPTION_EXECUTE_HANDLER;
BOOL bMiniDumpSuccessful;
TCHAR szPath[MAX_PATH];
TCHAR szFileName[MAX_PATH];
TCHAR* szAppName = TEXT(“AppName”);
TCHAR* szVersion = TEXT(“v1.0”);
DWORD dwBufferSize = MAX_PATH;
HANDLE hDumpFile;
SYSTEMTIME stLocalTime;
MINIDUMP_EXCEPTION_INFORMATION ExpParam;

GetLocalTime( &stLocalTime );
GetTempPath( dwBufferSize, szPath );

_stprintf( szFileName, TEXT(“%s%s”), szPath, szAppName );
CreateDirectory( szFileName, NULL );

_stprintf( szFileName, TEXT(“c:\\aaaa.dmp”));
hDumpFile = CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);

ExpParam.ThreadId = GetCurrentThreadId();
ExpParam.ExceptionPointers = pExceptionPointers;
ExpParam.ClientPointers = TRUE;

bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
hDumpFile, MiniDumpWithDataSegs, &ExpParam, NULL, NULL);

int i = GetLastError();
HRESULT hr = HRESULT_FROM_WIN32(i);

return ret;
}

2,在project setting中加入dbghelp.lib作为library的input,这是MiniDumpWriteDump需要的。在Debug Information Format设置Program Database (/Zi)。设置Generate Debug InfoYes (/DEBUG)。在Optimization设置ReferencesEliminate Unreferenced Data (/OPT:REF)。设置 Enable COMDAT FoldingRemove Redundant COMDATs (/OPT:ICF)。后面两项设置可以大大缩小exe文件大小。

3,使用如下:

void SomeFunction()
{
int *pBadPtr = NULL;
*pBadPtr = 0;
}
void Ctest2Dlg::OnBnClickedButton1()
{
__try
{
SomeFunction();
}
__except(GenerateDump(GetExceptionInformation()))
{
}
}

4,使用windbg打开dmp文件,就可以看到出错时的call stack了。

几点要注意的:1)网上有文章介绍使用 SetUnhandledExceptionFilter设置异常过滤,保证出现异常时能调用minidump函数,但是这有些问题,这个函数会导致debugger失效,而且好像跟drwatson有些冲突,感觉用起来比较危险。在程序的关键部分加入__try – __exception,这样缩小捕捉范围,应该就足够用了。2)必须是用__try – __exception这样的形式,才能保证GetExceptionInformation()能正常使用。3)MiniDumpWithDataSegs这个参数我试着换成另外几个,好像都不好用。返回值都是0,经过解析lasterror都是E_INVALIDARG,奇怪。

update: 关于使用windbg

windbg下载地址在这里http://www.microsoft.com/whdc/devtools/debugging/debugstart.mspx

下载安装最新版本即可,我没有搞清楚的一点是必须要设置windows的symbol目录,否则光有pdb是没法看到调用栈信息的。

使用windbg过程如下:安装。然后打开菜单file-> symbol file path,添加如下

srv*c:\symbol_local*http://msdl.microsoft.com/download/symbols;c:\debug

其中srv*c:\symbol_local*http://msdl.microsoft.com/download/symbols;指明从网上下载操作系统使用的symbol存放到c盘symbol_local目录,另外程序的symbol(pdb文件)可以放在c盘debug目录下。

windbg会显示一段时间busy或者retrieving..,然后就可以看到详细的dump信息了。

《Windows下C++编程生成minidump文件》有3个想法

  1. 对于试用了C++构造函数,好像就无法使用__try catch这个方式。印象中网上有介绍解决方法,准备写个新的文章介绍一下,另外关于SetUnxxx,也准备介绍。

  2. 多谢文章指引.
    ps:blog程序有点委琐.直接COPY你的代码,
    如:TEXT(“AppName”);
    其中的引号,被换成中文的了…

发表评论