MiniDump不生成或者生成0字节
今天在使用C写一个Windows多线程程序时,发现退出过程中有段错误,为了方便快速的定位问题,我使用了MiniDump。
MiniDump.c源码如下:
1#include <stdio.h>
2#include <stdlib.h>
3#include <time.h>
4#include <windows.h>
5#include <dbghelp.h>
6
7#pragma comment(lib, "dbghelp.lib")
8
9static LONG WINAPI ExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo)
10{
11 BOOL bDumpOK = FALSE;
12 wchar_t strDumpFileName[8192];
13 size_t len = 0;
14 wchar_t szPath[MAX_PATH];
15 if (GetModuleFileNameW(NULL, szPath, sizeof(szPath)))
16 {
17 time_t now = time(NULL);
18 struct tm *_t = localtime(&now);
19 len = swprintf(strDumpFileName, MAX_PATH, L"%ls.%4d%02d%02d_%02d%02d%02d.dmp", szPath,
20 _t->tm_year + 1900, _t->tm_mon + 1, _t->tm_mday, _t->tm_hour, _t->tm_min, _t->tm_sec);
21 HANDLE hFile = CreateFileW(strDumpFileName, FILE_ALL_ACCESS, 0, NULL, CREATE_ALWAYS, 0, NULL);
22 if (hFile != INVALID_HANDLE_VALUE)
23 {
24 MINIDUMP_EXCEPTION_INFORMATION exception_information;
25 exception_information.ThreadId = GetCurrentThreadId();
26 exception_information.ExceptionPointers = ExceptionInfo;
27 exception_information.ClientPointers = TRUE;
28 if (MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &exception_information, NULL, NULL))
29 bDumpOK = TRUE;
30 CloseHandle(hFile);
31 }
32 }
33
34 if (bDumpOK)
35 {
36 wchar_t *str = L"宕机了,MiniDump文件已经生成到:";
37 size_t num = wcslen(str);
38 memmove(&strDumpFileName[num], strDumpFileName, len * sizeof(wchar_t));
39 memcpy(strDumpFileName, str, num * sizeof(wchar_t));
40 MessageBoxW(NULL, strDumpFileName, L"提示", MB_OK);
41 }
42 else
43 {
44 MessageBoxW(NULL, L"宕机了,生成MiniDump文件失败。", L"提示", MB_OK);
45 }
46 return EXCEPTION_EXECUTE_HANDLER;
47}
48
49void InitMiniDump()
50{
51 SetUnhandledExceptionFilter(ExceptionFilter);
52}
但是测试了多次,要么是不能生成dump文件,要么生成的dump文件为0字节,之前在项目中使用C++时,专门做了一个CrashDumper的类,实际使用中是能够正常生成的:
MiniDump.h源码:
1#ifndef _MINI_DUMPER_H_
2#define _MINI_DUMPER_H_
3#ifdef _MSC_VER
4
5#include <windows.h>
6
7#pragma comment(linker, "/include:?dumper@@3VCrashDumper@@A")
8
9class CrashDumper
10{
11public:
12 CrashDumper();
13 ~CrashDumper();
14};
15
16#endif
17#endif
MiniDump.cpp源码:
1#ifdef _MSC_VER
2#pragma warning(disable:4091)
3#include <windows.h>
4#include <tchar.h>
5#include <dbghelp.h>
6#include <string>
7#include "MiniDump.h"
8
9#pragma comment(lib, "dbghelp.lib")
10
11static LPTOP_LEVEL_EXCEPTION_FILTER m_OriginalFilter;
12static LONG WINAPI ExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo)
13{
14 BOOL bDumpOK = FALSE;
15 wchar_t strDumpFileName[8192];
16 size_t len = 0;
17 wchar_t szPath[MAX_PATH];
18 if (GetModuleFileNameW(NULL, szPath, sizeof(szPath)))
19 {
20 time_t now = time(NULL);
21 struct tm *_t = localtime(&now);
22 len = swprintf(strDumpFileName, MAX_PATH, L"%ls.%4d%02d%02d_%02d%02d%02d.dmp", szPath,
23 _t->tm_year + 1900, _t->tm_mon + 1, _t->tm_mday, _t->tm_hour, _t->tm_min, _t->tm_sec);
24 HANDLE hFile = CreateFileW(strDumpFileName, FILE_ALL_ACCESS, 0, NULL, CREATE_ALWAYS, 0, NULL);
25 if (hFile != INVALID_HANDLE_VALUE)
26 {
27 MINIDUMP_EXCEPTION_INFORMATION exception_information;
28 exception_information.ThreadId = GetCurrentThreadId();
29 exception_information.ExceptionPointers = ExceptionInfo;
30 exception_information.ClientPointers = TRUE;
31 if (MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &exception_information, NULL, NULL))
32 bDumpOK = TRUE;
33 CloseHandle(hFile);
34 }
35 }
36
37 if (bDumpOK)
38 {
39 wchar_t *str = L"宕机了,MiniDump文件已经生成到:";
40 size_t num = wcslen(str);
41 memmove(&strDumpFileName[num], strDumpFileName, len * sizeof(wchar_t));
42 memcpy(strDumpFileName, str, num * sizeof(wchar_t));
43 MessageBoxW(NULL, strDumpFileName, L"提示", MB_OK);
44 }
45 else
46 {
47 MessageBoxW(NULL, L"宕机了,生成MiniDump文件失败。", L"提示", MB_OK);
48 }
49 return EXCEPTION_EXECUTE_HANDLER;
50}
51
52CrashDumper dumper;
53CrashDumper::CrashDumper()
54{
55 m_OriginalFilter = SetUnhandledExceptionFilter(ExceptionFilter);
56}
57
58CrashDumper::~CrashDumper()
59{
60 SetUnhandledExceptionFilter(m_OriginalFilter);
61}
62#endif
实际使用中只需要包含CrashDumper的头文件即可,VC++的编译器会自动链接。
今天的MiniDump却不能正常工作,在ExceptionFilter函数中打日志,时而有输出,时而没输出,有输出都是在函数开头的日志有输出,后面的就没输出了。网上查询了一些资料:
SetUnhandledExceptionFilter无法捕获异常原因及解决方法 SetUnhandledExceptionFilter拦不住的崩溃 SetUnhandledExceptionFilter 的讨论 为什么SetUnhandledExceptionFilter不能捕获某些异常,而AddVectoredExceptionHandler可以捕获
使用了这些方面,发现还是不行,最后在主线程main函数返回前加了一句:
1Sleep(1000);
即休眠一段时间,就生成了MiniDump了。
通过分析发现是另一个线程在退出时出现了宕机,但是主线程退出时还没来得及调用或者未完全调用完生成MiniDump文件,整个进程就结束了。简单粗暴的方法就是主函数退出前休眠一段时间,让异常处理程序有充分的时间生成MiniDump。
- 原文作者:Witton
- 原文链接:https://wittonbell.github.io/posts/2023/2023-03-22-MiniDump不生成或者生成0字节/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. 进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。