VS调试方法总结(二)

2 篇文章 0 订阅

通过结构化异常定位崩溃程序

程序崩溃时,生成文本文件,记录崩溃得堆栈信息

直接上代码

已经编译通过,拷贝直接可用

.h


#include <Windows.h>
#include <stdarg.h>
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>

#pragma once
#ifdef _WIN32
class CExceptionHandler
{
public:
	static LONG WINAPI CleanExceptionFun(struct _EXCEPTION_POINTERS* pei);

private:
	static void GetCurModulePath(TCHAR* ptcPath, int iLen, LPVOID addr);

	//static void EI2Str(TCHAR* ptcInfo,int iInfoLen,ULONG_PTR* Info,int iCount);
	static void EI2Str(char* ptcInfo, int iInfoLen, ULONG_PTR* Info, int iCount);

	static void TcharToChar(const TCHAR * tchar, char * _char);

	static void CharToTchar(const char * _char, TCHAR * tchar);
};
#else
#endif

.cpp

#include "stdafx.h"
#include "exceptionhandler.h"

#ifdef _WIN32
#include <DbgHelp.h>
#pragma comment(lib, "Dbghelp.lib")

#pragma warning(disable:4313)

void CExceptionHandler::GetCurModulePath(TCHAR* ptcPath, int iLen, LPVOID addr)
{
	MEMORY_BASIC_INFORMATION mbi = { 0 };
	if (FALSE == ::VirtualQuery(addr, &mbi, sizeof(mbi)))
		return;
	UINT_PTR h_module = (UINT_PTR)mbi.AllocationBase;
	::GetModuleFileName((HMODULE)h_module, ptcPath, iLen);
	return;
}

void CExceptionHandler::EI2Str(char* ptcInfo, int iInfoLen, ULONG_PTR* Info, int iCount)
{
	int        i = 0;
	char*    p1 = ptcInfo;

	for (i = 0; i < iCount; i++)
	{
		sprintf(p1, "%08X ", Info[i]);
		p1 += 9;
	}
}

void CExceptionHandler::TcharToChar(const TCHAR * tchar, char * _char)
{
	int iLength;
	iLength = WideCharToMultiByte(CP_ACP, 0, tchar, -1, NULL, 0, NULL, NULL);
	WideCharToMultiByte(CP_ACP, 0, tchar, -1, _char, iLength, NULL, NULL);
}


void CExceptionHandler::CharToTchar(const char * _char, TCHAR * tchar)
{
	int iLength;
	iLength = MultiByteToWideChar(CP_ACP, 0, _char, strlen(_char) + 1, NULL, 0);
	MultiByteToWideChar(CP_ACP, 0, _char, strlen(_char) + 1, tchar, iLength);
}


LONG WINAPI CExceptionHandler::CleanExceptionFun(struct _EXCEPTION_POINTERS* pei)
{
	STACKFRAME    sf;
	CONTEXT        context;
	TCHAR        tcPath[2048] = { 0 };
	TCHAR        tcInfo[10240] = { 0 };
	TCHAR        tcExcep[20480] = { 0 };
	GetCurModulePath(tcPath, 2048, pei->ExceptionRecord->ExceptionAddress);

	char szExcep[20480] = {};
	char szInfo[10240] = {};
	char szPath[2048] = {};
	//TcharToChar(tcInfo, szInfo);
	TcharToChar(tcPath, szPath);
	EI2Str(szInfo, 10240, pei->ExceptionRecord->ExceptionInformation, pei->ExceptionRecord->NumberParameters);

	sprintf(szExcep, "threadid: %u code: 0x%08X flag:0x%08X param:%d %s \nmoudle:%s \nstack:\n",
		GetCurrentThread(),
		pei->ExceptionRecord->ExceptionAddress,
		pei->ExceptionRecord->ExceptionFlags,
		pei->ExceptionRecord->ExceptionAddress,
		pei->ExceptionRecord->NumberParameters, szInfo, szPath);



	memset(tcInfo, 0, sizeof(tcInfo));
	memset(&sf, 0, sizeof(STACKFRAME));
	memcpy(&context, pei->ContextRecord, sizeof(CONTEXT));

	sf.AddrPC.Offset = context.Eip;
	sf.AddrPC.Mode = AddrModeFlat;
	sf.AddrStack.Offset = context.Esp;
	sf.AddrStack.Mode = AddrModeFlat;
	sf.AddrFrame.Offset = context.Ebp;
	sf.AddrFrame.Mode = AddrModeFlat;

	DWORD machineType = IMAGE_FILE_MACHINE_I386;
	HANDLE hProcess = GetCurrentProcess();
	HANDLE hThread = GetCurrentThread();
	SymInitialize(hProcess, NULL, TRUE);

	for (; ; )
	{
		if (!StackWalk(machineType, hProcess, hThread, &sf, &context, 0, SymFunctionTableAccess, SymGetModuleBase, 0))
		{
			break;
		}

		if (sf.AddrFrame.Offset == 0)
		{
			break;
		}
		BYTE symbolBuffer[sizeof(SYMBOL_INFO) + 1024];
		PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer;

		pSymbol->SizeOfStruct = sizeof(symbolBuffer);
		pSymbol->MaxNameLen = 1024;

		sprintf(szPath, "Offset:0x%08X ", sf.AddrPC.Offset);
		strcat(szExcep, szPath);


		memset(tcPath, 0, sizeof(tcPath));
		DWORD64 symDisplacement = 0;
		if (SymFromAddr(hProcess, sf.AddrPC.Offset, 0, pSymbol))
		{
			sprintf(szPath, "%s ", pSymbol->Name);
		}
		else
		{
			sprintf(szPath, "%s ", "Unknown symbol");
		}



		strcat(szExcep, szPath);



		IMAGEHLP_LINE lineInfo = { sizeof(IMAGEHLP_LINE) };
		DWORD dwLineDisplacement;

		memset(tcPath, 0, sizeof(tcPath));
		if (SymGetLineFromAddr(hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo))
		{
			sprintf(szPath, "[%s @ %u] ", lineInfo.FileName, lineInfo.LineNumber);
		}
		else
		{
		}
		strcat(szExcep, szPath);
		strcat(szExcep, "\n");


		//break;
	}
	strcat(szExcep, "\n");
	SymCleanup(hProcess);


	FILE* fp = fopen("C:\\Users\\pc\\Desktop\\1.txt", "w");
	if (NULL != fp)
	{

		fseek(fp, 0, SEEK_END);

		fprintf(fp, "%s", szExcep);

		fclose(fp);
		fp = NULL;
	}

	TerminateProcess(GetCurrentProcess(), 0);

	return EXCEPTION_EXECUTE_HANDLER;;
}
#else
#endif

以上代码可以正常执行

stdafx.h文件中无特殊头文件

main.cpp需要加上30、31这两行代码

#include "ExceptionHandler.h"

执行结果如下

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值