C++生成dump文件

C++代码中,使用DbgHelp模块的MINIDUMP编程生成

#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: 0xX %s Address: 0xX"),
              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: X"), 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);
}

  

posted @ 2016-10-09 16:13  sz_leez  阅读(4890)  评论(0编辑  收藏  举报