C++全局异常捕获和调试.dmp文件
在c++的程序运行过程中,有时需要分析异常产生的原因,所以首先需要捕获异常,生成crash文件(.dmp)之后,再用相关的调试工具去分析。
如何捕获异常,生成文件保存到本地?
先上代码:
#ifndef CRASH_EXCEPTION_H
#define CRASH_EXCEPTION_H
/**********************************************************************
*@projectName CrashTest
*@brief windows捕获全局异常写本地dump文件
*Author: zlozl
*Copyright: zlozl
*Email: zlozl5566@163.com
*QQ: 849414798
*BlogAddress: https://blog.csdn.net/ZLOZL
*GiteeHome: https://gitee.com/zlozl5566
*Version: V1.0.0.1
*Create Date: 2021-03-31
**********************************************************************/
/*
****************************************************************************************************
* windows平台建议选择MSVC编译器,可以用vs定位到出错代码行
****************************************************************************************************
*/
#ifdef _WIN32
#include <TCHAR.h>
#include "Windows.h"
#include "DbgHelp.h"
int GenerateMiniDump(PEXCEPTION_POINTERS pExceptionPointers)
{
// 定义函数指针
typedef BOOL(WINAPI * MiniDumpWriteDumpT)(
HANDLE,
DWORD,
HANDLE,
MINIDUMP_TYPE,
PMINIDUMP_EXCEPTION_INFORMATION,
PMINIDUMP_USER_STREAM_INFORMATION,
PMINIDUMP_CALLBACK_INFORMATION
);
// 从 "DbgHelp.dll" 库中获取 "MiniDumpWriteDump" 函数
MiniDumpWriteDumpT pfnMiniDumpWriteDump = NULL;
HMODULE hDbgHelp = LoadLibrary(_T("DbgHelp.dll"));
if (NULL == hDbgHelp)
{
return EXCEPTION_CONTINUE_EXECUTION;
}
pfnMiniDumpWriteDump = (MiniDumpWriteDumpT)GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
if (NULL == pfnMiniDumpWriteDump)
{
FreeLibrary(hDbgHelp);
return EXCEPTION_CONTINUE_EXECUTION;
}
// 创建 dmp 文件
TCHAR szFileName[MAX_PATH] = { 0 };
SYSTEMTIME stLocalTime;
GetLocalTime(&stLocalTime);
swprintf(szFileName, L"crash_%04d%02d%02d-%02d%02d%02d.dmp",
stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond);
HANDLE hDumpFile = CreateFile(szFileName, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
if (INVALID_HANDLE_VALUE == hDumpFile)
{
FreeLibrary(hDbgHelp);
return EXCEPTION_CONTINUE_EXECUTION;
}
// 写入 dmp 文件
MINIDUMP_EXCEPTION_INFORMATION expParam;
expParam.ThreadId = GetCurrentThreadId();
expParam.ExceptionPointers = pExceptionPointers;
expParam.ClientPointers = FALSE;
pfnMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
hDumpFile, MiniDumpWithDataSegs, (pExceptionPointers ? &expParam : NULL), NULL, NULL);
// 释放文件
CloseHandle(hDumpFile);
FreeLibrary(hDbgHelp);
return EXCEPTION_EXECUTE_HANDLER;
}
LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS lpExceptionInfo)
{
// 这里做一些异常的过滤或提示
if (IsDebuggerPresent())
{
return EXCEPTION_CONTINUE_SEARCH;
}
return GenerateMiniDump(lpExceptionInfo);
}
#endif // _WIN32
#endif // CRASH_EXCEPTION_H
测试示例:
#include "crash_exception.h"
int main()
{
// 加入崩溃dump文件功能
SetUnhandledExceptionFilter(ExceptionFilter);
// 使程序崩溃产生 Dump 文件
int *p = NULL;
*p = 1;
}
结果产生了crash文件。
如何分析crash文件?
通过Visual Studio工具可以分析,只需把.dmp文件托到编译器中,设置符号路径。
添加一下.pdb符号文件的路径,注意dump文件,程序编译生成的pdb文件(版本必须是产生崩溃的那个版本的编译信息),可执行文件(发生崩溃的版本)。如上图crash文件标志所示。
然后点击使用本机调试,就会跳转到产生异常的行数。