如何编写会崩溃并生成转储文件的示例代码?
Posted
技术标签:
【中文标题】如何编写会崩溃并生成转储文件的示例代码?【英文标题】:How to write a sample code that will crash and produce dump file? 【发布时间】:2011-06-29 01:33:11 【问题描述】:我开始学习windbg,我发现了这个好帖子 How to use WinDbg to analyze the crash dump for VC++ application?
现在我想按照说明一步一步地做。问题来了:我需要编写一些可以立即崩溃的示例代码,并创建一些可供windbg使用的转储文件。
这样的代码怎么写?
void Example4()
int* i = NULL;
*i = 80;
上面的代码会立即崩溃;但是,我不知道在哪里可以找到转储文件?
谢谢
【问题讨论】:
也看看这个:debuginfo.com/articles/effminidumps.html 我发现它非常有用。它还包含一些示例代码。 【参考方案1】:#include <Windows.h>
#include <Dbghelp.h>
void make_minidump(EXCEPTION_POINTERS* e)
auto hDbgHelp = LoadLibraryA("dbghelp");
if(hDbgHelp == nullptr)
return;
auto pMiniDumpWriteDump = (decltype(&MiniDumpWriteDump))GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
if(pMiniDumpWriteDump == nullptr)
return;
char name[MAX_PATH];
auto nameEnd = name + GetModuleFileNameA(GetModuleHandleA(0), name, MAX_PATH);
SYSTEMTIME t;
GetSystemTime(&t);
wsprintfA(nameEnd - strlen(".exe"),
"_%4d%02d%02d_%02d%02d%02d.dmp",
t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
auto hFile = CreateFileA(name, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if(hFile == INVALID_HANDLE_VALUE)
return;
MINIDUMP_EXCEPTION_INFORMATION exceptionInfo;
exceptionInfo.ThreadId = GetCurrentThreadId();
exceptionInfo.ExceptionPointers = e;
exceptionInfo.ClientPointers = FALSE;
auto dumped = pMiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
hFile,
MINIDUMP_TYPE(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory),
e ? &exceptionInfo : nullptr,
nullptr,
nullptr);
CloseHandle(hFile);
return;
LONG CALLBACK unhandled_handler(EXCEPTION_POINTERS* e)
make_minidump(e);
return EXCEPTION_CONTINUE_SEARCH;
int main()
SetUnhandledExceptionFilter(unhandled_handler);
return *(int*)0;
【讨论】:
【参考方案2】:这将产生一个空指针取消引用异常:
*((int*) 0) = 0;
这将产生整数除以零:
int a = 0; int b = 5 / a;
编辑:Post-Mortem Debugging Your Application with Minidumps and Visual Studio .NET 包含大量示例代码和有关使用小型转储的理论。
【讨论】:
感谢您的代码。你能告诉我在哪里可以找到转储文件吗? @q0987 该文件将在您使用 MiniDumpWriteDump() 写入的任何位置。如果你打开了 UAC,你可能无法直接在 C:\ 上写它。在这种情况下,请使用您用户下的文件夹,或以管理员身份启动应用程序。【参考方案3】:要创建故障转储,我将不按照@Abyx 的建议编写未处理的异常处理程序,原因如下:
a) 在某些缓冲区溢出或堆栈溢出的情况下,处理未处理异常的代码可能已损坏。如果出现 OutOfMemoryException,如何加载另一个库,如 DbgHelp.dll?
b) 你写的代码可能有问题。该代码是否在写入转储之前检查可用磁盘空间?您如何测试代码以编写故障转储?你有一个单元测试吗?您的单元测试如何检查转储是否正确?
c) 如果 Windows 可以为您编写代码,为什么还要编写代码?
MSDN 在Collecting user mode dumps 上有一篇文章。基本上,您可以进行一些注册表设置。优点是:Windows 将由操作系统创建故障转储,而不是由您自己的应用程序中的某些损坏的代码。
【讨论】:
有效点,但引用了 MSDN 文章Enabling the feature requires administrator privileges
,这对于软件部署可能是不可能的【参考方案4】:
如果您想查看故障转储,您需要创建一个。见Heisenbug: WinApi program crashes on some computers。虽然您可以在不通过 WinQual 的情况下获得旨在为 WER 发送的故障转储,但它有点混乱(基本上您可以在发送之前从临时位置复制它,具体细节取决于您的操作系统) ,我建议使用 Win API MiniDump 提供的函数创建自己的故障转储。所有需要的代码都可以在The CodeProject page mentioned in the linked answer找到。
【讨论】:
您还可以为您的应用配置一个位置,WER 将在其中保存小型转储。在此处查看更多详细信息:docs.microsoft.com/en-us/windows/win32/wer/…【参考方案5】:自动小型转储生成由事后调试器完成,因此您需要从那里开始。最重要的是,它是由调试器完成的。因此,如果您只想生成一个小型转储,您可以使用您的典型调试器(可能是 Visual Studio 或 Windbg)。甚至任务管理器也可以创建转储文件。
指定事后调试器的注册表设置是HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug
查看Debugger
字符串,您就可以找到您的小型转储了。
【讨论】:
【参考方案6】:转储文件可以通过编程或程序错误调试工具创建。在第一种情况下,您可以使用MiniDumpWriteDump 函数,在第二种情况下,您可以使用 Dr. Watson(对于 XP:看看这个 description 和这个非常具有描述性的 video;对于 Vista,看看 here)
【讨论】:
【参考方案7】:大多数情况下,您会发现所有应用程序都转储在 C:\windows\minidumps 中。
要生成转储文件,您可以使用简单的解决方案:
-
打开windbg
文件->打开可执行文件
您运行的应用程序会崩溃
会触发断点
现在您可以在 windbg 中使用 .dump 来创建 dmp 文件
或
-
运行应用程序并等待崩溃
打开windbg并附加到进程(文件->附加到进程)
运行.dump
这样您就可以随时分析该崩溃:)
【讨论】:
【参考方案8】:我前段时间测试WinDbg时使用了下面的代码。
下面的代码可以运行并将生成故障转储 有两个函数,因此您可以看到带有明显函数链的堆栈跟踪。 要查找故障转储,请在 C:\Users 中搜索 *.dmp 或 *.mdmp 最好让操作系统为您生成转储。这可能就是您看到的大多数真实故障转储的生成方式。 代码首先分配 1 KiB 的内存,然后用可识别的十六进制值写入它和后面的 1 KiB。这通常会遇到操作系统标记为不可写的内存页面,这将触发崩溃。#include "stdafx.h"
#include "stdio.h"
#include "malloc.h"
void Function2(int * ptr2)
for(int i=0; i < (2 * 1024); i++)
*ptr2++ = 0xCAFECAFE;
void Function1()
int * ptr1 = (int *)malloc(1024 * sizeof(int));
Function2(ptr1);
int _tmain(int argc, _TCHAR* argv[])
printf("Press enter to allocate and corrupt.\r\n");
getc(stdin);
printf("Allocating and corrupting...\r\n");
Function1();
printf("Done. Press enter to exit process.\r\n");
getc(stdin);
return 0;
【讨论】:
【参考方案9】:试试这个:
int main()
int v[5];
printf("%d", v[10]);
return 0;
或访问随机内存位置。
【讨论】:
这可能不会崩溃 - v[10] 处的堆栈内存可能实际上已分配,而 printf 只会打印出垃圾。以上是关于如何编写会崩溃并生成转储文件的示例代码?的主要内容,如果未能解决你的问题,请参考以下文章
Sun JDK 能否在 JVM 崩溃时生成核心/堆转储文件?