windows release版本exe自动记录崩溃日志信息

场景:

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)中,正确的记录了崩溃时的调用堆栈

其他

以上为项目中实际使用过的内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值