如何编写会崩溃并生成转储文件的示例代码?

发布于 2024-10-17 17:57:41 字数 390 浏览 2 评论 0原文

我开始学习windbg,发现这个好帖子 如何使用WinDbg分析崩溃VC++ 应用程序的转储?

现在我想按照说明一步一步进行。问题是:我需要编写一些可以立即崩溃的示例代码,并创建一些可供windbg 使用的转储文件。

这样的代码怎么写呢?

void Example4()
{
    int* i = NULL;
    *i = 80;
}

上面的代码会立即崩溃;但是,我不知道在哪里可以找到转储文件?

谢谢

I started learned windbg and I found this good post
How to use WinDbg to analyze the crash dump for VC++ application?

Now I want to follow the instructions and do it step by step. Here is the problem: I need to write some sample code that can immediately crash, and create some dump files that can be used by windbg.

How to write such code?

void Example4()
{
    int* i = NULL;
    *i = 80;
}

The above code will crash immediately; however, I don't know where to find the dump file?

Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

无风消散 2024-10-24 17:57:41
#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;
}
#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;
}
触ぅ动初心 2024-10-24 17:57:41

这将产生空指针解除引用异常:
*((int*) 0) = 0;

这将产生整数除以零:
int a = 0; int b = 5 / a;

编辑: 使用小型转储对应用程序进行事后调试Visual Studio .NET 包含大量有关使用小型转储的示例代码和理论。

This will produce a null pointer dereference exception:
*((int*) 0) = 0;

This will produce integer division by zero:
int a = 0; int b = 5 / a;

EDIT: Post-Mortem Debugging Your Application with Minidumps and Visual Studio .NET contains a lot of sample code and theory on using minidumps.

妄想挽回 2024-10-24 17:57:41

要创建故障转储,我不会按照@Abyx的建议编写未处理的异常处理程序,原因如下:

a)在出现某些缓冲区溢出或堆栈溢出的情况下,处理未处理的异常的代码可能已腐败。如果出现 OutOfMemoryException,如何加载另一个库,例如 DbgHelp.dll?

b) 您编写的代码可能有错误。该代码在写入转储之前是否检查可用磁盘空间?如何测试代码以编写故障转储?你有这方面的单元测试吗?您的单元测试如何检查转储是否正确?

c) 如果 Windows 可以为您编写代码,为什么还要编写代码呢?

MSDN 有一篇关于收集用户的文章模式转储。基本上,您可以进行一些注册表设置。优点是:Windows 将由操作系统创建故障转储,而不是由您自己的应用程序内的某些损坏的代码创建。

To create a crash dump, I would not write an unhandled exception handler as proposed by @Abyx for the following reasons:

a) in case of some buffer overflow or stack overflow, the code which handles the unhandled exception may be corrupt. In case of an OutOfMemoryException, how can you load another library like DbgHelp.dll?

b) the code which you have written may be buggy. Does that code check the free disk space before it writes the dump? How do you test the code to write a crash dump? Do you have a unit test for that? How does your unit test check if the dump is correct?

c) why write code at all if Windows can do it for you?

MSDN has an article on Collecting user mode dumps. Basically, there are some Registry settings which you can make. The advantage is: Windows will create the crash dump by the operating system, not by some corrupted code inside your own application.

你的心境我的脸 2024-10-24 17:57:41

如果您想查看故障转储,则需要创建一个。请参阅 Heisenbug:WinApi 程序在某些计算机上崩溃。虽然您也许能够在不通过 WinQual 的情况下获得打算发送给 WER 的故障转储,但这有点混乱(基本上您可以在发送之前从临时位置复制它,具体细节取决于您的操作系统) ,我建议使用 Win API MiniDump 提供的函数创建您自己的故障转储。为此所需的所有代码都可以在 链接答案中提到的 CodeProject 页面

If you want to see a crash dump, you need to create one. See Heisenbug: WinApi program crashes on some computers . While you may be able to get the crash dump intended to be send for WER without going through WinQual, it is a bit messy (basically you can copy it from the temporary location before it is sent away, exact details depend on your operating system), I would recommed to create your own crashdump using the Win API MiniDump provided functions. All code needed for this can be found at The CodeProject page mentioned in the linked answer.

不顾 2024-10-24 17:57:41

自动小型转储生成是由事后调试器完成的,因此您需要从那里开始。最重要的是,它是由调试器完成的。因此,如果您只想生成小型转储,则可以使用典型的调试器(可能是 Visual Studio 或 Windbg)。甚至任务管理器也可以创建转储文件。

指定事后调试器的注册表设置为 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug

查看 Debugger 字符串,您就可以上路了找到你的小型转储。

Auto minidump generation is done by the post-mortem debugger, so you need to start there. Most importantly though, it's done by a debugger. So if you just want to generate a minidump, you can use your typical debugger (probably visual studio or windbg). Even task manager can create dump files.

The registry setting which specifies the post-mortem debugger is HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug

Look at the Debugger string, and you will be on your way to finding your minidumps.

岁吢 2024-10-24 17:57:41

转储文件可以通过编程方式或通过程序错误调试器工具创建。在第一种情况下,您可以使用 MiniDumpWriteDump函数,第二个你可以使用 Dr. Watson(对于 XP:看看这个描述这个非常具有描述性的Vista 视频,请观看此处

Dump file can be created either programmaticaly or by program error debugger tool. In first case you can use MiniDumpWriteDump function and in the second you can use Dr. Watson (for XP: have a look at this description and this very descriptive video; for Vista, have a look here)

薄荷梦 2024-10-24 17:57:41

大多数时候,您会发现所有应用程序转储在 C:\windows\minidumps 中。

要生成转储文件,您可以使用一个简单的解决方案:

  1. 打开windbg
  2. 文件->打开可执行文件
  3. 您运行将崩溃的应用程序
  4. 将触发断点
  5. 现在您可以在windbg中使用.dump来创建dmp文件

  1. 运行应用程序并等待崩溃
  2. 打开windbg并附加到进程(文件->附加到进程)
  3. 运行.dump

这样您就可以随时分析崩溃:)

Most of the times you will find all apps dump in C:\windows\minidumps.

To generate a dump file you could use a simple solution:

  1. Open windbg
  2. File->Open Executable
  3. You run the app that will crash
  4. A breakpoint will trigger
  5. Now you can use .dump in windbg to create a dmp file

or

  1. Run the app and wait to crash
  2. Open windbg and attach to process (File->Attach to process)
  3. run .dump

This way you will be able to analyze that crash anytime :)

天荒地未老 2024-10-24 17:57:41

我前段时间测试 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;
}

I used the code below when testing out WinDbg some time ago.

  • The code below works and will generate a crash dump
  • There are two functions so that you can see a stack trace with an obvious chain of functions.
  • To find the crash dumps, search for *.dmp or *.mdmp in C:\Users
  • It's probably best to let the OS generate the dump for you. This is probably how most of the real crash dumps you see will be generated.
  • The code works by first allocating 1 KiB of memory, then writing both it and the following 1 KiB with a recognizable hexadecimal value. This usually hits a page of memory marked by the OS as non-writeable, which will trigger the crash.

#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;
}
手长情犹 2024-10-24 17:57:41

试试这个:

int main()
{
   int v[5];

   printf("%d", v[10]);
   return 0;
}

或者访问随机内存位置。

Try this:

int main()
{
   int v[5];

   printf("%d", v[10]);
   return 0;
}

or access a random memory location.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文