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 日志捕获保存堆栈到日志文件的主要内容,如果未能解决你的问题,请参考以下文章

MFC 日志捕获保存堆栈到日志文件

在 Kubernetes 中运行 ELK 堆栈的 Filebeat 不会在日志中捕获 pod 名称

MFC 保存运行日志

Unity 之 安卓堆栈跟踪和日志工具 (Android Logcat | 符号表解析Bugly捕获)

Unity 之 安卓堆栈跟踪和日志工具 (Android Logcat | 符号表解析Bugly捕获)

当用户单击“提交”按钮时将信息捕获到日志文件