Skip to content

Commit 4629207

Browse files
committed
新增程序崩溃时显示调用堆栈及每个模块的路径,便于对崩溃问题的定位
1 parent eb4513b commit 4629207

File tree

1 file changed

+95
-2
lines changed

1 file changed

+95
-2
lines changed

TrafficMonitor/crashtool.cpp

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "MessageDlg.h"
88
#include "Common.h"
99
#include "TrafficMonitor.h"
10+
#include <sstream>
1011

1112
#pragma comment(lib, "Dbghelp.lib")
1213

@@ -47,14 +48,106 @@ class CCrashReport
4748
::CloseHandle(hDumpFile);
4849
}
4950

50-
void ShowCrashInfo()
51+
//根据地址获取模块路径
52+
std::wstring GetModulePath(DWORD64 address)
53+
{
54+
// 获取模块信息
55+
HMODULE hModule = NULL;
56+
if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)address, &hModule))
57+
{
58+
TCHAR moduleName[MAX_PATH];
59+
if (GetModuleFileName(hModule, moduleName, MAX_PATH))
60+
{
61+
return moduleName;
62+
}
63+
}
64+
return L"Unknown Module";
65+
}
66+
67+
//获取崩溃堆栈信息
68+
std::wstring GetStackTrace(EXCEPTION_POINTERS* pExceptionInfo)
69+
{
70+
std::wstringstream stream;
71+
72+
// 初始化符号处理
73+
if (!SymInitialize(GetCurrentProcess(), NULL, TRUE))
74+
{
75+
stream << L"Failed to initialize symbol handler.\r\n";
76+
return stream.str();
77+
}
78+
79+
// RAII 确保 SymCleanup 被调用
80+
struct SymCleanupHelper {
81+
~SymCleanupHelper() { SymCleanup(GetCurrentProcess()); }
82+
} cleanupHelper;
83+
84+
STACKFRAME64 stackFrame = {};
85+
CONTEXT context = *pExceptionInfo->ContextRecord;
86+
87+
// 初始化堆栈帧
88+
#if defined _M_IX86
89+
DWORD machineType = IMAGE_FILE_MACHINE_I386;
90+
#elif defined _M_ARM64EC
91+
DWORD machineType = IMAGE_FILE_MACHINE_ARM64;
92+
#else
93+
DWORD machineType = IMAGE_FILE_MACHINE_AMD64;
94+
#endif
95+
stackFrame.AddrPC.Offset = context.Rip;
96+
stackFrame.AddrPC.Mode = AddrModeFlat;
97+
stackFrame.AddrFrame.Offset = context.Rbp;
98+
stackFrame.AddrFrame.Mode = AddrModeFlat;
99+
stackFrame.AddrStack.Offset = context.Rsp;
100+
stackFrame.AddrStack.Mode = AddrModeFlat;
101+
102+
// 遍历堆栈帧
103+
while (StackWalk64(machineType, GetCurrentProcess(), GetCurrentThread(), &stackFrame, &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) {
104+
if (stackFrame.AddrPC.Offset == 0) break;
105+
106+
// 获取符号信息
107+
BYTE symbolBuffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
108+
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer;
109+
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
110+
pSymbol->MaxNameLen = MAX_SYM_NAME;
111+
112+
DWORD64 displacement = 0;
113+
if (SymFromAddr(GetCurrentProcess(), stackFrame.AddrPC.Offset, &displacement, pSymbol)) {
114+
stream << L"Function: " << CCommon::AsciiToUnicode(pSymbol->Name) << L" (Displacement: " << displacement << L")\r\n";
115+
}
116+
else {
117+
stream << L"Unknown Function at address: " << (void*)stackFrame.AddrPC.Offset << L"\r\n";
118+
}
119+
120+
std::wstring modulePath = GetModulePath(stackFrame.AddrPC.Offset);
121+
if (!modulePath.empty())
122+
stream << L"Module Path: " << modulePath << L"\r\n";
123+
124+
// 获取源代码行信息
125+
IMAGEHLP_LINE64 line = {};
126+
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
127+
DWORD lineDisplacement = 0;
128+
if (SymGetLineFromAddr64(GetCurrentProcess(), stackFrame.AddrPC.Offset, &lineDisplacement, &line)) {
129+
stream << L"File: " << CCommon::AsciiToUnicode(line.FileName) << L" (Line: " << line.LineNumber << L")\r\n";
130+
}
131+
}
132+
return stream.str();
133+
}
134+
135+
void ShowCrashInfo(EXCEPTION_POINTERS* pEP)
51136
{
52137
CMessageDlg dlg;
53138
dlg.SetWindowTitle(APP_NAME);
54139
dlg.SetInfoText(CCommon::LoadText(IDS_ERROR_MESSAGE));
55140

56141
CString info = CCommon::LoadTextFormat(IDS_CRASH_INFO, { m_dumpFile });
57142
info += _T("\r\n");
143+
//在崩溃信息中调用堆栈
144+
std::wstring stack_trace = GetStackTrace(pEP);
145+
if (!stack_trace.empty())
146+
{
147+
info += _T("Stack trace:\r\n");
148+
info += stack_trace.c_str();
149+
info += _T("\r\n");
150+
}
58151
info += theApp.GetSystemInfoString();
59152
dlg.SetMessageText(info);
60153

@@ -105,7 +198,7 @@ namespace CRASHREPORT
105198
::SetErrorMode(0); //使用默认的
106199
CCrashReport cr;
107200
cr.CreateMiniDump(pEP);
108-
cr.ShowCrashInfo();
201+
cr.ShowCrashInfo(pEP);
109202
return EXCEPTION_CONTINUE_SEARCH;
110203
}
111204

0 commit comments

Comments
 (0)