是否有可能以编程方式创建迷你转储文件而不会崩溃?

时间:2017-04-03 20:43:29

标签: c++ debugging windows-7 windbg crash-dumps

假设远程站点出现罕见错误,但不会使应用程序崩溃。我还是想在发生这种情况时创建一个迷你转储文件,这样我就可以使用一些信息,主要是调用堆栈。

伪代码如下:

try
{
    doStuff();
}
catch(_com_error &e)
{
    make_minidump(); // is this possible?

    dump_com_error(e);
    return FALSE;
}

我看到的所有示例都要求我必须使应用程序崩溃(至少为了演示目的)才能生成转储文件,但我不想这样做。是否可以像这样创建转储文件?

我知道我可以去任务管理器并创建正在运行的进程的转储文件,同样我可以使用ProcessExplorer来实现相同的功能,所以看起来它应该是可能的。

同时在我看到的所有示例中,仅当控件来到SetUnhandledExceptionFilter时才会生成转储文件,该应用程序在应用程序崩溃时调用!

作为最后的手段,获取转储文件的唯一方法是故意使应用程序崩溃,如下所示:这会产生除崩溃之外的任何有用的东西吗?因为我知道在这种情况下导致崩溃的原因。

LONG CALLBACK unhandled_handler(EXCEPTION_POINTERS* e)
{
    make_minidump(e);
    return EXCEPTION_CONTINUE_SEARCH;
}

int main()
{
    SetUnhandledExceptionFilter(unhandled_handler);

    return *(int*)0;
}

1 个答案:

答案 0 :(得分:2)

是的,当然。类似于Windows任务管理器可以创建正在运行/挂起的应用程序的崩溃转储而没有任何异常,您可以使用MiniDumpWriteDump()来创建崩溃转储。只需通过NULL ExceptionParam

以下是一些可能有用的代码:

typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile,
        MINIDUMP_TYPE DumpType,
        CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
        CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
        CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam
                                        );

const wchar_t * DBGHELP = L"DbgHelp.dll";

bool Dump(const std::wstring & dumpFile)
{
    bool success = false;
    DllLoader loader;

    // Load dbghelp.dll. Try first to find it in the application directory.
    loader.Load(::GetModuleHandle(NULL), DBGHELP);
    if (!loader.IsLoaded())
    {
        loader.Load(DBGHELP);
    }

    if (loader.IsLoaded())
    {
        MINIDUMPWRITEDUMP pDump = MINIDUMPWRITEDUMP(loader.GetProcAddress("MiniDumpWriteDump"));

        if (pDump)
        {
            // Create dump file
            HANDLE fileHandle = ::CreateFileW(dumpFile.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS,
                                              FILE_ATTRIBUTE_NORMAL, nullptr);

            if (fileHandle != INVALID_HANDLE_VALUE)
            {
                BOOL bOK = pDump(GetCurrentProcess(), GetCurrentProcessId(), fileHandle, MiniDumpWithFullMemory, nullptr, nullptr, nullptr);
                if (bOK)
                {
                    success = true;
                }

                ::CloseHandle(fileHandle);
            }
        }
    }

    return success;
}

由于优化,我无法在k中看到正确的堆栈,但dds ebp显示了它:

0029f8d0  01302029 GetCrashWithDLL!MethodB+0x99 [f:\...\getcrashwithdll.cpp @ 12]
[...]
0029f914  0130209c GetCrashWithDLL!wmain+0x3c [f:\...\getcrashwithdll.cpp @ 31]
[...]
0029f920  01302cff GetCrashWithDLL!__tmainCRTStartup+0xfd [f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c @ 623]