MiniDump不生成或者生成0字节

今天在使用C写一个Windows多线程程序时,发现退出过程中有段错误,为了方便快速的定位问题,我使用了MiniDump。

MiniDump.c源码如下:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include <dbghelp.h>

#pragma comment(lib, "dbghelp.lib")

static LONG WINAPI ExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo)
{
	BOOL bDumpOK = FALSE;
	wchar_t strDumpFileName[8192];
	size_t len = 0;
	wchar_t szPath[MAX_PATH];
	if (GetModuleFileNameW(NULL, szPath, sizeof(szPath)))
	{
		time_t now = time(NULL);
		struct tm *_t = localtime(&now);
		len = swprintf(strDumpFileName, MAX_PATH, L"%ls.%4d%02d%02d_%02d%02d%02d.dmp", szPath,
					   _t->tm_year + 1900, _t->tm_mon + 1, _t->tm_mday, _t->tm_hour, _t->tm_min, _t->tm_sec);
		HANDLE hFile = CreateFileW(strDumpFileName, FILE_ALL_ACCESS, 0, NULL, CREATE_ALWAYS, 0, NULL);
		if (hFile != INVALID_HANDLE_VALUE)
		{
			MINIDUMP_EXCEPTION_INFORMATION exception_information;
			exception_information.ThreadId = GetCurrentThreadId();
			exception_information.ExceptionPointers = ExceptionInfo;
			exception_information.ClientPointers = TRUE;
			if (MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &exception_information, NULL, NULL))
				bDumpOK = TRUE;
			CloseHandle(hFile);
		}
	}

	if (bDumpOK)
	{
		wchar_t *str = L"宕机了,MiniDump文件已经生成到:";
		size_t num = wcslen(str);
		memmove(&strDumpFileName[num], strDumpFileName, len * sizeof(wchar_t));
		memcpy(strDumpFileName, str, num * sizeof(wchar_t));
		MessageBoxW(NULL, strDumpFileName, L"提示", MB_OK);
	}
	else
	{
		MessageBoxW(NULL, L"宕机了,生成MiniDump文件失败。", L"提示", MB_OK);
	}
	return EXCEPTION_EXECUTE_HANDLER;
}

void InitMiniDump()
{
	SetUnhandledExceptionFilter(ExceptionFilter);
}

但是测试了多次,要么是不能生成dump文件,要么生成的dump文件为0字节,之前在项目中使用C++时,专门做了一个CrashDumper的类,实际使用中是能够正常生成的:

MiniDump.h源码:

#ifndef _MINI_DUMPER_H_
#define _MINI_DUMPER_H_
#ifdef _MSC_VER

#include <windows.h>

#pragma comment(linker, "/include:?dumper@@3VCrashDumper@@A")

class CrashDumper
{
public:
	CrashDumper();
	~CrashDumper();
};

#endif
#endif

MiniDump.cpp源码:

#ifdef _MSC_VER
#pragma warning(disable:4091)
#include <windows.h>
#include <tchar.h>
#include <dbghelp.h>
#include <string>
#include "MiniDump.h"

#pragma comment(lib, "dbghelp.lib")

static LPTOP_LEVEL_EXCEPTION_FILTER m_OriginalFilter;
static LONG WINAPI ExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo)
{
	BOOL bDumpOK = FALSE;
	wchar_t strDumpFileName[8192];
	size_t len = 0;
	wchar_t szPath[MAX_PATH];
	if (GetModuleFileNameW(NULL, szPath, sizeof(szPath)))
	{
		time_t now = time(NULL);
		struct tm *_t = localtime(&now);
		len = swprintf(strDumpFileName, MAX_PATH, L"%ls.%4d%02d%02d_%02d%02d%02d.dmp", szPath,
					   _t->tm_year + 1900, _t->tm_mon + 1, _t->tm_mday, _t->tm_hour, _t->tm_min, _t->tm_sec);
		HANDLE hFile = CreateFileW(strDumpFileName, FILE_ALL_ACCESS, 0, NULL, CREATE_ALWAYS, 0, NULL);
		if (hFile != INVALID_HANDLE_VALUE)
		{
			MINIDUMP_EXCEPTION_INFORMATION exception_information;
			exception_information.ThreadId = GetCurrentThreadId();
			exception_information.ExceptionPointers = ExceptionInfo;
			exception_information.ClientPointers = TRUE;
			if (MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &exception_information, NULL, NULL))
				bDumpOK = TRUE;
			CloseHandle(hFile);
		}
	}

	if (bDumpOK)
	{
		wchar_t *str = L"宕机了,MiniDump文件已经生成到:";
		size_t num = wcslen(str);
		memmove(&strDumpFileName[num], strDumpFileName, len * sizeof(wchar_t));
		memcpy(strDumpFileName, str, num * sizeof(wchar_t));
		MessageBoxW(NULL, strDumpFileName, L"提示", MB_OK);
	}
	else
	{
		MessageBoxW(NULL, L"宕机了,生成MiniDump文件失败。", L"提示", MB_OK);
	}
	return EXCEPTION_EXECUTE_HANDLER;
}

CrashDumper dumper;
CrashDumper::CrashDumper()
{
	m_OriginalFilter = SetUnhandledExceptionFilter(ExceptionFilter);
}

CrashDumper::~CrashDumper()
{
	SetUnhandledExceptionFilter(m_OriginalFilter);
}
#endif

实际使用中只需要包含CrashDumper的头文件即可,VC++的编译器会自动链接。

今天的MiniDump却不能正常工作,在ExceptionFilter函数中打日志,时而有输出,时而没输出,有输出都是在函数开头的日志有输出,后面的就没输出了。网上查询了一些资料:

SetUnhandledExceptionFilter无法捕获异常原因及解决方法
SetUnhandledExceptionFilter拦不住的崩溃
SetUnhandledExceptionFilter 的讨论
为什么SetUnhandledExceptionFilter不能捕获某些异常,而AddVectoredExceptionHandler可以捕获

使用了这些方面,发现还是不行,最后在主线程main函数返回前加了一句:

Sleep(1000);

即休眠一段时间,就生成了MiniDump了。

通过分析发现是另一个线程在退出时出现了宕机,但是主线程退出时还没来得及调用或者未完全调用完生成MiniDump文件,整个进程就结束了。简单粗暴的方法就是主函数退出前休眠一段时间,让异常处理程序有充分的时间生成MiniDump。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值