Chinaunix首页 | 论坛 | 博客
  • 博客访问: 315829
  • 博文数量: 240
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 50
  • 用 户 组: 普通用户
  • 注册时间: 2016-08-04 18:14
文章分类

全部博文(240)

文章存档

2017年(8)

2014年(4)

2013年(15)

2012年(4)

2011年(14)

2010年(55)

2009年(140)

我的朋友

分类: WINDOWS

2009-09-26 22:40:03

   程序崩溃(crash)的时候, 为了以后能够调试分析问题, 可以使用WinDBG要把当时程序内存空间数据都保存下来,生成的文件称为dump 文件。
 
步骤:
1) 打开WinDBG并将之Attach 到crash的程序进程
2) 输入产生dump 文件的命令
WinDBG产生dump 文件的命令是 .dump ,可以选择不同的参数来生成不同类型的dump文件。
 
选项(1): /m
命令行示例:.dump /m C:\dumps\myapp.dmp
注解: 缺省选项,生成标准的minidump, 转储文件通常较小,便于在网络上通过邮件或其他方式传输。 这种文件的信息量较少,只包含系统信息、加载的模块(DLL)信息、 进程信息和线程信息。
 
选项(2): /ma
命令行示例:.dump /ma C:\dumps\myapp.dmp
注解: 带有尽量多选项的minidump(包括完整的内存内容、句柄、未加载的模块,等等),文件很大,但如果条件允许(本机调试,局域网环境), 推荐使用这中dump。
 
选项(3):/mFhutwd
命令行示例:.dump /mFhutwd C:\dumps\myapp.dmp
注解:带有数据段、非共享的读/写内存页和其他有用的信息的minidump。包含了通过minidump能够得到的最多的信息。是一种折中方案。
 
 
 
 
 
 
   上面介绍如如何用WinDBG 生成crash dump 《WinDBG 技巧:如何生成Dump 文件(.dump 命令) 》,但是用户机器上通常不安装WinDBG, 而且多数用户也不知道怎么使用WinDBG。 所以最好是自己程序里面能够捕捉exception/crash,并且生成crash dump,然后通过网络传回到自己服务器。
 
捕捉exception 可以用API 函数 SetUnhandledExceptionFilter 。
生成crash dump 可以用DbgHelp.dll 里面的MiniDumpWriteDump 函数。
 
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter( __in LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter );
 
BOOL WINAPI MiniDumpWriteDump( __in HANDLE hProcess, __in DWORD ProcessId, __in HANDLE hFile, __in MINIDUMP_TYPE DumpType, __in PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, __in PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, __in PMINIDUMP_CALLBACK_INFORMATION CallbackParam );
 
 
 
【代码实例】
 

#include <dbghelp.h>
#include <shellapi.h>
#include <shlobj.h>
  
  
// 自定义的exectpion filter

LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *pExceptionPointers)
{
  
    SetErrorMode( SEM_NOGPFAULTERRORBOX );
  
    
//收集信息

     CStringW strBuild;
    strBuild.Format(L"Build: %s %s", __DATE__, __TIME__);
    CStringW strError;
    HMODULE hModule;
    WCHAR szModuleName[MAX_PATH] = L"";
    GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)pExceptionPointers->ExceptionRecord->ExceptionAddress, &hModule);
    GetModuleFileName(hModule, szModuleName, ARRAYSIZE(szModuleName));
    strError.AppenedFormat(L"%s %d , %d ,%d.", szModuleName,pExceptionPointers->ExceptionRecord->ExceptionCode, pExceptionPointers->ExceptionRecord->ExceptionFlags, pExceptionPointers->ExceptionRecord->ExceptionAddress);
  
    
//生成 mini crash dump

    BOOL bMiniDumpSuccessful;
    WCHAR szPath[MAX_PATH];
    WCHAR szFileName[MAX_PATH];
    WCHAR* szAppName = L"AppName";
    WCHAR* szVersion = L"v1.0";
    DWORD dwBufferSize = MAX_PATH;
    HANDLE hDumpFile;
    SYSTEMTIME stLocalTime;
    MINIDUMP_EXCEPTION_INFORMATION ExpParam;
    GetLocalTime( &stLocalTime );
    GetTempPath( dwBufferSize, szPath );
    StringCchPrintf( szFileName, MAX_PATH, L"%s%s", szPath, szAppName );
    CreateDirectory( szFileName, NULL );
    StringCchPrintf( szFileName, MAX_PATH, L"%s%s\\%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",
               szPath, szAppName, szVersion,
               stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
               stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,
               GetCurrentProcessId(), GetCurrentThreadId());
    hDumpFile = CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE,
                FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
  
    MINIDUMP_USER_STREAM UserStream[2];
    MINIDUMP_USER_STREAM_INFORMATION UserInfo;
    UserInfo.UserStreamCount = 1;
    UserInfo.UserStreamArray = UserStream;
    UserStream[0].Type = CommentStreamW;
    UserStream[0].BufferSize = strBuild.GetLength()*sizeof(WCHAR);
    UserStream[0].Buffer = strBuild.GetBuffer();
    UserStream[1].Type = CommentStreamW;
    UserStream[1].BufferSize = strError.GetLength()*sizeof(WCHAR);
    UserStream[1].Buffer = strError.GetBuffer();
  
    ExpParam.ThreadId = GetCurrentThreadId();
    ExpParam.ExceptionPointers = pExceptionPointers;
    ExpParam.ClientPointers = TRUE;
       
    MINIDUMP_TYPE MiniDumpWithDataSegs = MiniDumpNormal
            | MiniDumpWithHandleData
            | MiniDumpWithUnloadedModules
            | MiniDumpWithIndirectlyReferencedMemory
            | MiniDumpScanMemory
            | MiniDumpWithProcessThreadData
            | MiniDumpWithThreadInfo;
    bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
                    hDumpFile, MiniDumpWithDataSegs, &ExpParam, NULL, NULL);
  
// 上传mini dump 到自己服务器(略)

  ...
  
  return EXCEPTION_CONTINUE_SEARCH;
//或者 EXCEPTION_EXECUTE_HANDLER 关闭程序

}
    
int _tmain()
{
  
// 设置 execption filter

  SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
  ....
  return 0;
}

 
 

正常情况下不会生成dump,需要自己在程序中添加代码实现,一般是利用MS的dbghelp.dll提供的DbgHelpCreateUserDump来生成,用WinDbg来分析,期间需要编译程序生成的.pdb文件。可以参考BlackBox、google breakpad等
 
crash 文件生成的路径:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug]
"Auto"="0"
"Debugger"="\"D:\\WinDBG\\ntsd.exe\" -p %ld -e %ld -g -noio -c \".dump /ma /u d:\\dbgdmp\\dmp.dmp; q"
"UserDebuggerHotKey"=dword:00000000
阅读(2919) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~