注意:部分代码收集于网络。
.pro
#生成dump文件需要
LIBS += -lDbgHelp
swcrash.h
#ifndef SWCRASH_H
#define SWCRASH_H
#include <windows.h>
//
#include "qdebug.h"
#include "qmessagebox.h"
#include <dbghelp.h> //捕获异常地址,用addr2line进行查找具体代码位置
#include <signal.h> //捕获SIGSEGV
void swcrashInit();
#endif // SWCRASH_H
swcrash.cpp
#include "swcrash.h"
/**
* @brief 程序异常捕获
* @param
* @retval
*/
LONG ApplicationCrashHandler(EXCEPTION_POINTERS *pException) {
// 创建 Dump 文件
qWarning() << "=========================异常信息==========================";
QString createPath = QCoreApplication::applicationDirPath() + "/dumps";
QDir dir;
dir.mkpath(createPath);
createPath = QString("%1/dump_%2.dmp")
.arg(createPath)
.arg(QDateTime::currentDateTime().toString(
"yyyy_MM_dd_hh_mm_ss_zzz"));
std::wstring wlpstr = createPath.toStdWString();
LPCWSTR lpcwStr = wlpstr.c_str();
HANDLE hDumpFile = CreateFile(lpcwStr, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hDumpFile != INVALID_HANDLE_VALUE) {
// Dump信息
MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
dumpInfo.ExceptionPointers = pException;
dumpInfo.ThreadId = GetCurrentThreadId();
dumpInfo.ClientPointers = FALSE;
// 写入Dump文件内容
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile,
MiniDumpNormal, &dumpInfo, NULL, NULL);
qWarning() << "ExceptionPointers:" << dumpInfo.ExceptionPointers;
}
// 这里弹出一个错误对话框并退出程序
EXCEPTION_RECORD *record = pException->ExceptionRecord;
QString errCode(QString::number(record->ExceptionCode, 16)),
errAdr(QString::number((UINT)((UINT_PTR)record->ExceptionAddress), 16));
qWarning() << "ExceptionCode:" << errCode;
qWarning() << "ExceptionAddress:" << errAdr;
qWarning() << "ExceptionInformation:" << record->ExceptionInformation;
qWarning() << "NumberParameters:" << record->NumberParameters;
qWarning() << "========================================================";
QMessageBox::critical(NULL, "异常信息",
"<FONT size=4><div><b>致命错误</b><br/></div>" +
QString("<div>错误代码:%1</div><div>错误地址:%2</"
"div></FONT>")
.arg(errCode)
.arg(errAdr),
QMessageBox::Ok);
return EXCEPTION_EXECUTE_HANDLER;
}
/**
* @brief 打印异常信息
* @param
* @retval
*/
void SegmentationHandle(int sig) {
qWarning() << "=========================致命错误==========================";
qWarning() << "Segmentation value:" << sig;
switch (sig) {
case 11:
qWarning() << "SIGSEGV";
break;
// 其它错误号码,以后遇到在增加
default:
break;
}
qWarning() << "========================================================";
}
/**
* @brief 初始化异常信息捕获
* @param
* @retval
*/
void swcrashInit() {
// 注冊异常捕获函数
SetUnhandledExceptionFilter(
(LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);
// 系统异常信号
signal(SIGSEGV, SegmentationHandle);
signal(SIGINT, SegmentationHandle);
// 后续遇到其它信号再增加
}
使用方法
#include <QApplication>
#include "mainwindow.h"
#include "swlog.h"
#include "swcrash.h"
int main(int argc, char *argv[]) {
LogFileInit(); // 生成log.txt
swcrashInit(); // 捕获异常信息
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
然后用addr2line -f -e xxxx.exe 40c463去定位故障位置。
提示:
1.自动在执行文件的目录新建一个dumps的文件夹。
2.该方法不可以获取 class的空指针,例如: QPushButton *ab = nullptr。
3.对于int类型空指针有效,例如: int *a = nullptr。