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

时间:2011-02-17 12:13:24

标签: c++ visual-c++ windbg

我开始学习windbg并找到了这篇好文章 How to use WinDbg to analyze the crash dump for VC++ application?

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

如何编写此类代码?

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

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

谢谢

9 个答案:

答案 0 :(得分:29)

#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;
}

答案 1 :(得分:4)

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

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

编辑:Post-Mortem Debugging Your Application with Minidumps and Visual Studio .NET包含大量使用小型转储的示例代码和理论。

答案 2 :(得分:1)

如果要查看崩溃转储,则需要创建一个。见Heisenbug: WinApi program crashes on some computers。虽然您可以在不通过WinQual的情况下获得故意发送给WER的故障转储,但它有点混乱(基本上您可以在它被发送之前从临时位置复制它,具体细节取决于您的操作系统) ,我建议使用Win API MiniDump提供的函数创建自己的crashdump。可以在The CodeProject page mentioned in the linked answer找到所需的所有代码。

答案 3 :(得分:1)

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

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

查看Debugger字符串,您就可以找到您的小型转发了。

答案 4 :(得分:1)

转储文件可以通过programmaticaly或程序错误调试工具创建。在第一种情况下,你可以使用MiniDumpWriteDump功能,在第二种情况下,你可以使用Dr. Watson(对于XP:看看这个description和这个非常具有描述性的video;对于Vista,有看看here

答案 5 :(得分:1)

要创建崩溃转储,我会编写@Abyx建议的未处理异常处理程序,原因如下:

a)在某些缓冲区溢出或堆栈溢出的情况下,处理未处理异常的代码可能已损坏。如果出现OutOfMemoryException,如何加载像DbgHelp.dll这样的其他库?

b)你写的代码可能有问题。该代码是否在写入转储之前检查可用磁盘空间?你如何测试代码来编写崩溃转储?你有单元测试吗?您的单元如何检查转储是否正确?

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

MSDN上有一篇关于Collecting user mode dumps的文章。基本上,您可以进行一些注册表设置。优点是:Windows将通过操作系统创建崩溃转储,而不是由您自己的应用程序中的某些损坏的代码创建。

答案 6 :(得分:0)

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

答案 7 :(得分:0)

大多数情况下,您会在C:\ windows \ minidumps中找到所有应用程序转储。

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

  1. 打开windbg
  2. 文件 - &gt;打开可执行文件
  3. 您运行将崩溃的应用
  4. 断点将触发
  5. 现在你可以在windbg中使用.dump创建一个dmp文件
    1. 运行应用程序并等待崩溃
    2. 打开windbg并附加到进程(文件 - &gt;附加到进程)
    3. run .dump
    4. 通过这种方式,您可以随时分析崩溃:)

答案 8 :(得分:-3)

试试这个:

int main()
{
   int v[5];

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

或访问随机内存位置。