Vs中使用dump文件调试程序崩溃
2013-04-08 09:13
471 查看
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在哪个线程中的。
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在哪个线程中的。
相关文章推荐
- 使用VS调试Dump文件
- vc调试:使用MAP文件快速定位程序崩溃代码行-zz
- 使用WinDbg抓取程序报错的Dump文件,例如抓取IE崩溃的Dump
- VS 2005使用map文件查找程序崩溃原因
- VS 2005使用map文件查找程序崩溃原因
- VS 2005使用map文件查找程序崩溃原因
- vc调试:使用MAP文件快速定位程序崩溃代码行
- 使用WinDbg抓取程序报错的Dump文件,例如抓取IE崩溃的Dump
- VS 2005使用map文件查找程序崩溃原因
- 让程序崩溃时生成dump文件以供调试
- VS 2005使用map文件查找程序崩溃原因
- 程序崩溃 dump 文件 *.kdmp的使用
- VS 2005使用map文件查找程序崩溃原因(转载,很好)
- VS 2005使用map文件查找程序崩溃原因
- VS 2005使用map文件查找程序崩溃原因
- VS 2005使用map文件查找程序崩溃原因
- 程序崩溃 dump 文件 *.kdmp的使用
- 使用Dump文件让程序在崩溃时体面的退出
- 使用windbg分析程序崩溃后附加windbg dump出来的dmp文件
- VS 2005使用map文件查找程序崩溃原因