背景
我们的Windows c++程序如果在客户或者没有代码调试的环境下崩溃了。我们只能从机器异常报错里得知寥寥无几的信息,如果程序崩溃时,能自动触发当前堆栈信息的收集,那么对于开发人员复现BUG就尤为重要
CrashRpt
CrashRpt主要功能
1.崩溃报告收集:当应用程序崩溃时,CrashRpt会自动收集与崩溃相关的信息,包括崩溃堆栈跟踪、异常代码、CPU寄存器状态等。生成Visual studio或者Windbg可以调试的dump文件
2.崩溃报告生成:CrashRpt能够将收集到的信息压缩成zip文件,及保留异常时的屏幕快照
3.崩溃报告传输:CrashRpt支持将崩溃报告通过电子邮件、HTTP、FTP等方式传输到指定目的地
CrashRpt源码下载
注意
在实际场景下,有少数异常崩溃,异常捕获模块可能捕捉不到,或者感知到后,在生成dump文件时产生了二次崩溃,这样就没有dump文件可供分析了。遇到这类问题,则需要使用Windbg将程序启动起来或者将Windbg附加到已经启动的程序进程上,即将Windbg挂到目标进程上和目标进程一起跑,如果目标进程发生异常,Windbg会第一时间感知到并中断下来,这样就可以拿到函数调用堆栈进行分析了。
CrashRpt编译
下载好源码后,里面的文件默认是Win32的。我们需要x64的需要额外编译,直接打开sln,注意这边需要关闭该选项否则会出现
无法打开文件“atls.lib”
编译好后生成如下文件和lib
CrashRpt使用
以测试为例,我们在VS里配置好incldue和lib,同时关闭优化,生成pdb文件。我们程序一般发布都是release版本,如果优化开启有可能会造成dump的行数和实际的代码对不上,因为编译器已经把你的代码进行了优化,如果实在要开启,不要开启O3级别,O3连for循环都会优化
然后我们在程序启动的地方初始化CrashRpt库,
#include "testDump.h"
#include <QtWidgets/QApplication>
#include <QDebug>
#include "CrashRpt.h"
class TestCrashRpt
{
public:
TestCrashRpt()
{
CR_INSTALL_INFO info;
memset(&info, 0, sizeof(CR_INSTALL_INFO));
info.cb = sizeof(CR_INSTALL_INFO);
// 1. 设置文件名称和版本号
std::wstring wsappName = L"testWidgte";
std::wstring wsappVersion = L"1.0.0.1";
info.pszAppName = wsappName.c_str();
info.pszAppVersion = wsappVersion.c_str();
//Install all available exception handlers.
info.dwFlags |= CR_INST_ALL_POSSIBLE_HANDLERS;
info.dwFlags |= CR_INST_DONT_SEND_REPORT;
//把Dump压缩成zip文件
info.dwFlags |= CR_INST_STORE_ZIP_ARCHIVES;
info.dwFlags |= CR_INST_AUTO_THREAD_HANDLERS;
//指定崩溃生成的文件夹,注意这要使用windows的路径\\,不要使用\,否则该库无法正常生成文件
std::wstring wsreportPath = L"D:\\DumpTest";
info.pszErrorReportSaveDir = wsreportPath.c_str();
//指定生成MiniDump
info.uMiniDumpType = (MINIDUMP_TYPE)(MiniDumpWithFullMemory);
int nResult = crInstall(&info);
//安装到程序里
if (nResult != 0)
{
qDebug() << "crInstall failed";
return;
}
// 截取屏幕快照当程序崩溃时
// crAddScreenshot2(CR_AS_MAIN_WINDOW | CR_AS_USE_JPEG_FORMAT, 95);
}
~TestCrashRpt()
{
//卸载crashrpt
crUninstall();
}
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
TestCrashRpt crashRpt;
testDump w;
w.show();
return a.exec();
}
直接运行,程序出现崩溃并收集
我们可以看到“D:\DumpTest”下已经生成了对应的dump
打开dump查看堆栈
1.用复制dmp文件到项目运行目录,用Visual studio即可打开这个dump
2.使用本机进行调试,他会自动加载项目底下的pdb,然后搜索对应的代码,如果你是Wingdb调试。他会一开始要你指定pdb目录和源码目录,道理是一样的