带有MiniDumpWriteDump的_set_se_translator何时无法写入转储?

时间:2019-02-15 14:04:37

标签: c++ crash-dumps

我们在Windows上的32位C ++可执行文件中发生了罕见的崩溃,该崩溃不会产生内存转储。我们没有问题的案例,当崩溃发生时,游戏仅在几秒钟后消失,因此我们需要进行内存转储以查找原因。其他崩溃确实会产生内存转储,因此我们知道我们的内存转储功能有时会起作用,只是在此特定崩溃上不起作用。

在什么情况下_set_se_translatorMiniDumpWriteDump的组合不会产生内存转储?我们在内存转储处理中做错了什么,导致有时不产生转储吗?

这是我们目前正在做的事情:

在主线程的主函数开始处,我们调用SetUnhandledExceptionFilter(CrashDumpManager::unhandledExceptionHandler);

在每个线程中,我们称为_set_se_translator(CrashDumpManager::MiniDumpFunction);

这是CrashDumpManager.h的样子:

#include <Windows.h>
#include <Dbghelp.h>

class CrashDumpManager
{
public:
    static void MiniDumpFunction(unsigned int nExceptionCode, EXCEPTION_POINTERS *pException);
    static LONG CALLBACK unhandledExceptionHandler(EXCEPTION_POINTERS* e);

    //If the game crashes because of a memory leak then there won't be enough memory free to generate a memory dump
    //Therefore 10MB is allocated here and deleted before the crashdump is written.
    static unsigned char* crashdumpMemory;
};

这是CrashDumpManager.cpp的样子:

#include "CrashDumpManager.h"

void CrashDumpManager::MiniDumpFunction(unsigned int nExceptionCode, EXCEPTION_POINTERS *pException)
{
    delete crashdumpMemory;
    crashdumpMemory = nullptr;

    // prevent stack overflow when crashing in this function
    static bool calledFunctionOnce = false;
    if (!calledFunctionOnce)
    {
        calledFunctionOnce = true;

        HMODULE dbgHelpModule = LoadLibraryA("dbghelp");
        if (dbgHelpModule == nullptr)
            return;
        auto writeMiniDumpFunction = (decltype(&MiniDumpWriteDump))GetProcAddress(dbgHelpModule, "MiniDumpWriteDump");
        if (writeMiniDumpFunction == nullptr)
            return;

        char name[MAX_PATH];
        {
            char* nameEnd = name + GetModuleFileNameA(GetModuleHandleA(0), name, MAX_PATH);
            SYSTEMTIME t;
            GetSystemTime(&t);
            wsprintfA(nameEnd - strlen(".exe"), "_%4d%02d%02d_%02d%02d%02d.mdmp",
                      t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
        }

        HANDLE dumpFileHandle = CreateFileA(name, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
        if (dumpFileHandle == INVALID_HANDLE_VALUE)
            return;

        MINIDUMP_EXCEPTION_INFORMATION exceptionInfo;
        exceptionInfo.ThreadId = GetCurrentThreadId();
        exceptionInfo.ExceptionPointers = pException;
        exceptionInfo.ClientPointers = FALSE;

        auto dumped = writeMiniDumpFunction(GetCurrentProcess(), GetCurrentProcessId(), dumpFileHandle,
                                            MINIDUMP_TYPE(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory),
                                            pException ? &exceptionInfo : nullptr, nullptr, nullptr);

        CloseHandle(dumpFileHandle);
    }
}

LONG CALLBACK CrashDumpManager::unhandledExceptionHandler(EXCEPTION_POINTERS* e)
{
    CrashDumpManager::MiniDumpFunction(0, e);
    return EXCEPTION_CONTINUE_SEARCH;
}

unsigned char* CrashDumpManager::crashdumpMemory = new unsigned char[10*1024*1024];

0 个答案:

没有答案