头文件
#include <windows.h>
#include <QDebug>
#pragma comment(lib, "dbghelp.lib")
class CCrashStack
{
public:
CCrashStack(PEXCEPTION_POINTERS pException);
void generateDumpFile(struct _EXCEPTION_POINTERS* exceptionInfo);
QStringList SaveCallStack(const EXCEPTION_POINTERS* pException);
private:
PEXCEPTION_POINTERS m_pException;
};
cpp
//key :
// 1. CaptureStackBackTrace(0, maxFrames, framePointers, nullptr);
// 2. SYMBOL_INFO symbolInfo;
// 3. SymFromAddr(process, (DWORD64)(framePointers[i]), nullptr, &symbolInfo)
#include <tlhelp32.h>
#include "DbgHelp.h"
#include "LogServer.h"
CCrashStack::CCrashStack(PEXCEPTION_POINTERS pException)
{
m_pException = pException;
}
const int MAX_STACK_FRAMES = 64;
const int MAX_SYM_NAME_LEN = 64;
QStringList CCrashStack::SaveCallStack(const EXCEPTION_POINTERS* pException)
{
QStringList callStack;
const int maxFrames = 50;
void* framePointers[maxFrames];
unsigned int frameCount = CaptureStackBackTrace(0, maxFrames, framePointers, nullptr);
HANDLE process = GetCurrentProcess();
SymInitialize(process, nullptr, TRUE);
for (unsigned int i = 0; i < frameCount; ++i)
{
SYMBOL_INFO symbolInfo;
symbolInfo.SizeOfStruct = sizeof(SYMBOL_INFO);
symbolInfo.MaxNameLen = 256;
if (SymFromAddr(process, (DWORD64)(framePointers[i]), nullptr, &symbolInfo))
{
callStack.push_back(QString("%1 : Address : %2")
.arg(symbolInfo.Name)
.arg(symbolInfo.Address));
// IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE64) };
// if (SymGetLineFromAddr64(process, (DWORD64)(framePointers[i]), nullptr, &lineInfo))
// {
// callStack.push_back(QString("%1 : Address : %2")
// .arg(lineInfo.FileName)
// .arg(lineInfo.LineNumber));
// } else {
// callStack.push_back(QString("<unknown file> : Address : 0"));
// }
} else
{
callStack.push_back("<unknown>");
}
}
// for (const auto& frame : callStack)
// {
// LOGE(QString(frame));
// }
SymCleanup(process);
return callStack;
}
void CCrashStack::generateDumpFile(struct _EXCEPTION_POINTERS* exceptionInfo)
{
QStringList sCrashInfo = SaveCallStack(exceptionInfo);
QString Time = CURRENT_TIME_MS;
QString sFileName = "testcrash_" + Time + ".log";
QFile file(sFileName);
if (file.open(QIODevice::WriteOnly|QIODevice::Truncate))
{
file.write("Dump Stack Info : \n");
for (int i = 0; i < sCrashInfo.size(); i++)
file.write(sCrashInfo[i].toUtf8() + "\n");
file.write("\n\n");
file.write("Log Info : \n");
QStringList messageList = LogServer::instance()->messageList();
for (int i = 0; i < messageList.size(); i++)
file.write(messageList[i].toUtf8());
file.close();
}
qDebug()<<"Error:\n"<<sCrashInfo;
QString CrashDump = QString("CrashDump_%1.dmp").arg(Time);
HANDLE hDumpFile = CreateFile(CrashDump.toStdWString().c_str(),
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
dumpInfo.ThreadId = GetCurrentThreadId();
dumpInfo.ExceptionPointers = exceptionInfo;
dumpInfo.ClientPointers = TRUE;
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);
CloseHandle(hDumpFile);
}
how to callback: SetUnhandledExceptionFilter
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
SetUnhandledExceptionFilter(callback);
return a.exec();
}
result
Dump Stack Info :
CCrashStack::SaveCallStack : Address : 140696195610800
<unknown>
callback : Address : 140696195637056
UnhandledExceptionFilter : Address : 140720007597360
memcpy : Address : 140720052592384
_C_specific_handler : Address : 140720052498688
_chkstk : Address : 140720052585200
RtlFindCharInUnicodeString : Address : 140720052034000
KiUserExceptionDispatcher : Address : 140720052581344
QByteArray::QByteArray : Address : 140718069457184
EvaluatorThread::run : Address : 140717834213072
QThread::start : Address : 140718071360352
BaseThreadInitThunk : Address : 140720023741792
RtlUserThreadStart : Address : 140720052283952
Log Info :
"[2024-04-09 10:56:05:009] [2608] [D] [ LinearityTester] 294 : 479.862,798.501,795.139,534.052,"
"[2024-04-09 10:56:05:009] [2608] [D] [ GC32E1] exposureTime = 295, realExposureTime = 295, line = 295"
"[2024-04-09 10:56:05:009] [2608] [D] [ DxDevicePrivate] [I2C][W] slaveID = 0x94, reg = 0x0202, value = 0x0001, mode = 0x3"
"[2024-04-09 10:56:05:010] [2608] [D] [ DxDevicePrivate] [I2C][W] slaveID = 0x94, reg = 0x0203, value = 0x0027, mode = 0x3"
"[2024-04-09 10:56:05:010] [2608] [D] [ LinearityTester] abandon frame : 0"
"[2024-04-09 10:56:05:070] [2608] [D] [ LinearityTester] abandon frame : 1"
"[2024-04-09 10:56:05:136] [2608] [D] [ LinearityTester] abandon frame : 2"
wait to do
// IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE64) };
// if (SymGetLineFromAddr64(process, (DWORD64)(framePointers[i]), nullptr, &lineInfo))
// {
// callStack.push_back(QString("%1 : Address : %2")
// .arg(lineInfo.FileName)
// .arg(lineInfo.LineNumber));
// } else {
// callStack.push_back(QString("<unknown file> : Address : 0"));
// }
You may use SymGetLineFromAddr64 to get line infomation.
Howerver, even i`ve produce the .dmp data, i haven`t get the expected result