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;
}

猜你喜欢

转载自blog.csdn.net/PZ0605/article/details/121911162