C++生成dump文件

轉自:http://www.cnblogs.com/sz-leez/p/5942692.html

C++代碼中,使用DbgHelp模塊的MINIDUMP編程生成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#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中加入代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
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);
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章