Vs中使用dump文件调试程序崩溃

Vs中使用dump文件调试程序崩溃

 

1. Dump文件的生成

在vs中要生成dump文件需要加入一些代码,这些代码在debug或release代码下均有效果。

首先定义异常类:

class CSE_Exception {

     public:

         CSE_Exception() : m_nSENumber(0) {}

 

         unsigned int       m_nSENumber;

         EXCEPTION_RECORD   m_SERecord;

         CONTEXT                m_SEContext;

 

         // set SE handler, for CSE_Exception.  应该为每个线程调用

         static void InitSEException();

         static long _DbgDumpError(struct _EXCEPTION_POINTERS *excpInfo, LPCTSTR szPrex);

         static void _DumpSystemInfo(LPTSTR szDump, int nSize);

         static void _DumpCallStack();

     private:

         static void trans_func( unsigned int uSENum, _EXCEPTION_POINTERS* pExp );

     };

 

其实现为:

#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: 0x%08X %s Address: 0x%08X"),

              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: %08X"), 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);

}

 

这样就可以了。

 

还有在 编译的时候,还要把.pdb文件放好,放在运行的目录下,则要一致对应。

 

2. 使用dump文件进行调试

首先用vs2008将它打开,点调试。

下面就下载符号表才行。

点 工具à调试à符号

再点增加, 在符号文件.pdb路径下加入:: http://msdl.microsoft.com/download/symbols

在下面的文本框中加入一个本地存放pdb解析文件的路径如:c:\Symbols

 

上面的下载过程很慢,如果下载完成,则会断下,这时,在 调试中打开调用栈,打开线程,

一个一个线程进行分析,看程序是core在哪个线程中的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值