MiniDump不生成或者生成0字节

2023-11-17

今天在使用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。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MiniDump不生成或者生成0字节 的相关文章

随机推荐

  • Oracle 高CPU SQL查找

    先top命令 找到PID 再在SQL界面用管理员权限查询 select sql text spid v session program process from v sqlarea v session v process where v s
  • 史上最全的CSS hack方式一览

    http blog csdn net freshlover article details 12132801
  • charge用法

    I mean I can stop charging anytime I want 老友记 第一季 第一集 我的意思是 我可以随时忍住挥霍 及物动词 vt 1 索价 对 索费 课 税 O1 for This store often char
  • socket超时设置 之 ioctlsocket 函数全面解析

    先看看MSDN标准解释 int ioctlsocket SOCKET s long cmd u long FAR argp Parameters s in Descriptor identifying a socket cmd in Com
  • SVN客户端安装及使用

    SVN客户端安装及使用 安装svn客户端 svn常用命令 将指定仓库checkout到当前目录 添加指定文件 添加所有文件 提交文件 更新文件 更新当前目录所有文件 更新指定文件 删除文件 查看修改记录 查看当前目录的修改记录 查看某个文件
  • 车险保单在线OCR识别,字段很全,可以可以

    快瞳科技 车险保单识别 在线测试后发现 保险公司名称 保单号或者合同号 总保费 保险期间 业务类型 车型保单类型 保单名称 被保人信息 被保险人 被保人姓名 被保人证件号码 被保人电话号码 被保人联系地址 车辆信息 车牌 车辆种类 车辆使用
  • 二分查找4 - 搜索旋转排序数组

    搜索旋转数组 1 题目 整数数组 nums 按升序排列 数组中的值 互不相同 在传递给函数之前 nums 在预先未知的某个下标 k 0 lt k lt nums length 上进行了 旋转 使数组变为 nums k nums k 1 nu
  • 秒天秒地!黑马王炸学科,均薪18k+,最高42000元!

    掌握AI的同学 握住了高薪密码 黑马北京校区人工智能开发 16 班的就业炸了 毕业仅 7 个工作日 班级就业率便达到 65 班级均薪高达 18340 9 元 最高薪资更是冲到了 42k 班级就业详情数据 滑动沾高薪喜气 看完这无敌的就业喜报
  • Three.js使用OrbitControls后修改相机旋转方向无效

    1 问题复现 在项目中添加了OrbitControls控制器来控制相机的旋转和平移 但是需要修改初始的相机角度 于是我把相机的角度进行修改 如下 const camera new THREE PerspectiveCamera 75 vie
  • linux nginx 配置

    http blog csdn net Colton Null article details 78439174 locationNum 8 fps 1 之前发布过一篇如何在Tomcat中配置二级域名 现在发现几个月前的我太年轻了 哎 过几个
  • Leetcode算法——63、不重复路径II(unique paths II)

    一个机器人位于一个m n的网格的左上角 它每次只能向下或向右移动一格 它试图到达网格的右下角 网格中有一些障碍物 机器人不能通过 求有多少种不重复的路径 备注 1 m 和 n 都不大于 100 2 障碍物和空地分别被标为 1 和 0 示例
  • 如何开发一个小程序游戏?

    小程序游戏开发需要开发人员具备以下几点能力 有一定的编程基础 例如 JavaScript TypeScript 至少熟悉一种游戏开发引擎 比如 Cocos Unity等 对游戏机制 游戏系统有一定的理解 有一定的 UI 界面审美 能够开脑洞
  • 字典树Trie和三叉搜索树Ternary Tree的学习总结

    字典树Trie和三叉搜索树Ternary Tree的学习总结 出处 西西整理 作者 西西 日期 2012 12 31 2 39 04 大 中 小 评论 0 我要发表看法 Trie树 又称字典树 单词查找树或者前缀树 是一种用于快速检索的多叉
  • 第38讲 Android Camera2 API 通过CropRegion控制Zoom缩放

    本讲是Android Camera专题系列的第38讲 我们介绍Android Camera2 API专题的通过CropRegion控制Zoom缩放 包括如下内容 Android Zoom简介 如何查询当前Camera支持的Zoom能力 通过
  • pycharm中from,import文件/模块出现问题(最全方法)

    1 引用本地文件 如上图所示 在pycharm中可能会出现引用 本地项目文件夹中的 py文件出现问题的时候 这时我们需要考虑是否是IDE环境未将项目路径设置到引用环境变量中 有一下几种方法可以解决 1 这时可以通过sys path inse
  • iOS开源系列——OC框架排名列表

    Objective C框架排名 快点我
  • PRD文档范例,产品经理值得收藏的写作手册

    2015年 我写了一篇梳理PRD的文章 PRD到底该怎么写 获得3 5万次阅读 423次收藏 至今已过去5年 在这5年里 我一直从事产品产品相关的工作 也经历过一次完整的创业 对PRD又有了一些新的思考 这篇文章是 PRD怎么写 的升级版
  • 软件测试方法——静态测试与动态测试

    从测试方法的角度可以分为手工测试和自动化测试 1 静态测试 所谓静态测试 static testing 就是不实际运行被测软件 而只是静态地检查程序代码 界面或文档中可能存在的错误的过程 从概念中我们可以知道 其包括对代码测试 界面测试和文
  • Python re.match函数的使用详解

    正则表达式是用于匹配和操作文本的强大工具 在Python中 re模块提供了一组函数来处理正则表达式 其中 re match函数用于尝试从字符串的起始位置匹配一个模式 本文将详细介绍re match函数的使用方法 并提供相应的源代码示例 re
  • MiniDump不生成或者生成0字节

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