场景:
windows CMake cpp工程
可以访问main.cpp和部分源码,由于某些特殊原因,只能发布为release版本。现在需要软件的崩溃日志
功能实现
在main.cpp中添加如下代码:
#include <Windows.h>
#include <iostream>
#include <fstream>
#include <DbgHelp.h>
LONG WINAPI MyExceptionHandler(EXCEPTION_POINTERS* pExceptionInfo) {
// Log exception info to a file
std::ofstream logfile("D:\\crash_log.txt", std::ios::app);
logfile << "Crash details:" << QDateTime::currentDateTime().toString("yyyy-MM-dd hh-mm-ss").toStdString().c_str() << std::endl;
logfile << "Exception code: " << pExceptionInfo->ExceptionRecord->ExceptionCode << std::endl;
logfile << "Exception address: " << pExceptionInfo->ExceptionRecord->ExceptionAddress << std::endl;
// Initialize the DbgHelp library
SymInitialize(GetCurrentProcess(), NULL, TRUE);
// Capture the call stack
void* stack[64]; // A reasonable size for the stack trace
unsigned short frames = CaptureStackBackTrace(0, 64, stack, NULL);
logfile << "Call stack:\n";
for (unsigned short i = 0; i < frames; i++) {
DWORD64 address = (DWORD64)(stack[i]);
// Resolve the symbol for the address
SYMBOL_INFO* symbol = (SYMBOL_INFO*)malloc(sizeof(SYMBOL_INFO) + 256);
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
symbol->MaxNameLen = 255;
// Retrieve symbol information
if (SymFromAddr(GetCurrentProcess(), address, 0, symbol)) {
logfile << " #" << i << " " << symbol->Name << " at " << std::hex << symbol->Address << std::dec << std::endl;
} else {
logfile << " #" << i << " [Unknown function] at " << std::hex << address << std::dec << std::endl;
}
free(symbol);
}
SymCleanup(GetCurrentProcess());
return EXCEPTION_EXECUTE_HANDLER; // Continue execution, or you can terminate as needed
}
int main(int argc, char *argv[])
{
SetUnhandledExceptionFilter(MyExceptionHandler);
//your code
}
D:\crash_log.txt 是个人配置的崩溃日志路径,可以自行修改
另一个需要注意的是CMakeLists.txt中需要链接的是DbgHelp.Lib而非.dll,个人的路径为:
C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x64\DbgHelp.Lib
这个需要根据项目自行修改为x64或x86版本
测试:
如下为手动写入崩溃代码的2次测试
Crash details:2025-02-24 11-31-52
Exception code: 3221225477
Exception address: 00007FF793D08F05
Call stack:
#0 MyExceptionHandler at 7ff793d07a00
#1 UnhandledExceptionFilter at 7ffd6f291120
#2 memcpy at 7ffd719f6f40
#3 _C_specific_handler at 7ffd719df730
#4 _chkstk at 7ffd719f5330
#5 RtlFindCharInUnicodeString at 7ffd7196ddf0
#6 KiUserExceptionDispatcher at 7ffd719f4430
#7 main at 7ff793d08ed0
#8 __scrt_common_main_seh at 7ff793d0c23c
#9 BaseThreadInitThunk at 7ffd70a52580
#10 RtlUserThreadStart at 7ffd719aaf10
Crash details:2025-02-24 11-33-59
Exception code: 3221225477
Exception address: 00007FF7B311371A
Call stack:
#0 MyExceptionHandler at 7ff7b3147a00
#1 UnhandledExceptionFilter at 7ffd6f291120
#2 memcpy at 7ffd719f6f40
#3 _C_specific_handler at 7ffd719df730
#4 _chkstk at 7ffd719f5330
#5 RtlFindCharInUnicodeString at 7ffd7196ddf0
#6 KiUserExceptionDispatcher at 7ffd719f4430
#7 SiClient::slotReceiveMessages at 7ff7b3113700
#8 QObject::qt_static_metacall at 7ffca8410940
#9 TcpSocket::sigSocketReadyRead at 7ffcbae49d80
#10 TcpSocket::readyRead at 7ffcbae35be0
#11 QObject::qt_static_metacall at 7ffca8410940
#12 QAbstractSocket::canReadLine at 7ffcb216e430
#13 QLocalSocket::socketDescriptor at 7ffcb21793f0
#14 QApplicationPrivate::notify_helper at 7ffcacab4880
#15 QApplication::notify at 7ffcacab2160
#16 QCoreApplication::notifyInternal2 at 7ffca83f2a10
#17 QEventDispatcherWin32::processEvents at 7ffca843b9f0
#18 DispatchMessageW at 7ffd6f767cb0
#19 DispatchMessageW at 7ffd6f767cb0
#20 QEventDispatcherWin32::processEvents at 7ffca843b9f0
#21 qt_plugin_query_metadata at 7ffcadc60e40
#22 QEventLoop::exec at 7ffca83eed70
#23 QCoreApplication::exec at 7ffca83f1940
#24 main at 7ff7b3148ed0
#25 __scrt_common_main_seh at 7ff7b314c22c
#26 BaseThreadInitThunk at 7ffd70a52580
#27 RtlUserThreadStart at 7ffd719aaf10
可以看到第一次崩溃在main(#7)中,第二次崩溃在SiClient::slotReceiveMessages(#7)中,正确的记录了崩溃时的调用堆栈
其他
以上为项目中实际使用过的内容