MFC 日志捕获保存堆栈到日志文件
Posted 绿叶清风
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MFC 日志捕获保存堆栈到日志文件相关的知识,希望对你有一定的参考价值。
- 捕获异常
__try
int j = 0;
int i = 1 / j;
BYTE* pch;
pch = (BYTE*)00001234; //给予一个非法地址
*pch = 6; //对非法地址赋值,会造成Access Violation 异常
__except (EXCEPTION_EXECUTE_HANDLER)
CString stackInfo;
if (LogUtil::GetTraceStack(&stackInfo) != NULL) //获取堆栈信息
LOG(ERROR) << "程序发生了错误:" << stackInfo;//将堆栈信息存到文件
printf("stackInfo:%s \\n",stackInfo);
- 修改配置:
这时候直接编译,可能会提示:error C2712: 无法在要求对象展开的函数中使用__try,我们需要修改配置 ,如图:
- LogUtil.h头文件
#pragma once
#include "stdafx.h"
class LogUtil
public:
//LogUtil::LogUtil();
static CString * GetTraceStack(CString *message);
;
- LogUtil.c文件
#include "stdafx.h"
#include "LogUtil.h"
#include <windows.h>
#include <dbghelp.h>
#include <stdio.h>
#pragma comment(lib, "version.lib")
#pragma comment( lib, "dbghelp.lib" )
#include <exception>
#include <iostream>
#define STACK_INFO_LEN 1024
static const int MAX_STACK_FRAMES = 12;
//LogUtil::LogUtil()
//
//
//
CString * LogUtil::GetTraceStack(CString *message)
void *pStack[MAX_STACK_FRAMES];
static char szStackInfo[STACK_INFO_LEN * MAX_STACK_FRAMES];
static char szFrameInfo[STACK_INFO_LEN];
HANDLE process = GetCurrentProcess();
SymInitialize(process, NULL, TRUE);
typedef WORD(_stdcall *PFUNRtlCaptureStackBackTrace)(
DWORD FramesToSkip,
DWORD FramesToCapture,
PVOID* BackTrace,
PDWORD BackTraceHash
);
HMODULE hNt = LoadLibrary(_T("NtDll.dll"));
PFUNRtlCaptureStackBackTrace
pCaptureStackBackTrace = (PFUNRtlCaptureStackBackTrace)
GetProcAddress(hNt, ("RtlCaptureStackBackTrace"));
if (!pCaptureStackBackTrace)
return NULL;
WORD frames = pCaptureStackBackTrace(0, MAX_STACK_FRAMES, pStack, NULL);
TCHAR szBuffer[sizeof(SYMBOL_INFOW) + MAX_SYM_NAME * sizeof(TCHAR)];
DWORD64 dwAddress = 0;
DWORD64 dwDisplacement = 0;
PSYMBOL_INFOW pSymbol = NULL;
DWORD dwDisplacement2 = 0;
IMAGEHLP_LINEW64 ilLine;
for (WORD i = 0; i < frames; ++i)
DWORD64 address = (DWORD64)(pStack[i]);
DWORD64 displacementSym = 0;
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
pSymbol->MaxNameLen = MAX_SYM_NAME;
DWORD displacementLine = 0;
IMAGEHLP_LINE64 line;
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
if (SymFromAddr(process, address, &displacementSym, pSymbol) && SymGetLineFromAddr64(process, address, &displacementLine, &line))
snprintf(szFrameInfo, sizeof(szFrameInfo), "\\t%s() at %s:%d(0x%x)\\n", pSymbol->Name, line.FileName, line.LineNumber, pSymbol->Address);
strcat(szStackInfo, szFrameInfo);
else
//snprintf(szFrameInfo, sizeof(szFrameInfo), "\\terror: %d\\n", GetLastError());
//strcat(szStackInfo, szFrameInfo);
message->Format(_T("%s"), szStackInfo);
FreeLibrary(hNt);
return message;
以上是关于MFC 日志捕获保存堆栈到日志文件的主要内容,如果未能解决你的问题,请参考以下文章
在 Kubernetes 中运行 ELK 堆栈的 Filebeat 不会在日志中捕获 pod 名称
Unity 之 安卓堆栈跟踪和日志工具 (Android Logcat | 符号表解析Bugly捕获)