【问题标题】:Is it possible to create mini dump file programmatically without a crash?是否可以以编程方式创建迷你转储文件而不会崩溃?
【发布时间】:2017-08-28 20:48:23
【问题描述】:

假设远程站点出现罕见错误,但没有使应用程序崩溃。发生这种情况时,我仍然想创建一个小型转储文件,以便我有一些信息可以使用,主要是调用堆栈。

伪代码如下:

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

【问题讨论】:

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


【解决方案1】:

是的,当然。类似于 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]

【讨论】:

  • 我同时尝试了this 并创建了转储文件,但基本 EBP 指针为 0x00000,它不会中断我的函数。我正在查看您的代码,但不确定 DllLoader 是什么?谢谢。
  • DllLoader 只是 ::LoadLibrary() 的一个包装器。没什么特别的。
  • @zar:该代码应该从进程外部创建故障转储。只要你的函数不是很长时间运行或挂起,你就需要幸运地将你的函数放在调用堆栈上。
  • 正确的是没有破坏函数,所以如果没有适当的调用堆栈,我不知道这有什么用处。我在一个简单的演示应用程序中执行此操作,它甚至不会触及我的应用程序代码。
  • @zar:然后使用我的代码。如您所见,MethodB 可见
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
  • 2014-06-13
  • 2011-06-16
  • 1970-01-01
  • 2011-08-22
相关资源
最近更新 更多