• windows生成dump文件


    windows下程序有时突然崩溃了,偶发性的崩溃很难找。于是就需要保存崩溃时的dump信息了。

    下面是关于如何生成dmp文件的代码。

    头文件

    #pragma once
    #include <windows.h>
    #include <DbgHelp.h>
    #include <stdlib.h>
    #include <string>
    #pragma comment(lib, "dbghelp.lib")
    
    
    namespace FrameworkMiniDump
    {
        std::wstring GetTimeNowString();
        std::string WStringToString(const std::wstring& str);
        std::wstring StringToWString(const std::string& str);
        std::string getexepath();
        inline BOOL IsDataSectionNeeded(const WCHAR* pModuleName);
    
        inline BOOL CALLBACK MiniDumpCallback(PVOID                            pParam,
            const PMINIDUMP_CALLBACK_INPUT   pInput,
            PMINIDUMP_CALLBACK_OUTPUT        pOutput);
    
        inline void CreateMiniDump(PEXCEPTION_POINTERS pep, LPCTSTR strFileName);
        LONG __stdcall MyUnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo);
        void DisableSetUnhandledExceptionFilter();// 此函数一旦成功调用,之后对 SetUnhandledExceptionFilter 的调用将无效
        void InitMinDump();
    }

    源文件:

    #include "MiniDump.h"
    #include <iostream>
    #include <ctime>
    #include <string>
    
    namespace FrameworkMiniDump
    {
        std::wstring GetTimeNowString()
        {
            time_t rawtime;
            struct tm * timeinfo;
            wchar_t buffer[80];
    
            time(&rawtime);
            timeinfo = localtime(&rawtime);
    
            //wcsftime(buffer, sizeof(buffer), L"%d-%m-%Y %H:%M:%S", timeinfo);
            wcsftime(buffer, sizeof(buffer), L"%d-%m-%Y-%H-%M-%S", timeinfo);
            std::wstring str(buffer);
            return str;
        }
    
    
        std::wstring StringToWString(const std::string& str)
        {
    #if defined(WIN32)
            size_t sz = str.length();
            int nd = MultiByteToWideChar(CP_ACP, 0, &str[0], sz, NULL, 0);
            std::wstring ret(nd, 0);
            int w = MultiByteToWideChar(CP_ACP, 0, &str[0], sz, &ret[0], nd);
            if (str.length() != sz) {
    
                throw std::exception("StringToWString Err");
            }
            return ret;
    #else
            const char* p = str.c_str();
            size_t len = str.length();
            size_t sz = len * sizeof(wchar_t);
            wchar_t* tp = new wchar_t[sz];
            size_t w = mbstowcs(tp, p, sz);
            if (w != len) {
                delete[] tp;
                throw std::exception("StringToWString Err");
            }
            std::wstring ret(tp);
            delete[] tp;
            return ret;
    #endif
        }
    
        std::string WStringToString(const std::wstring& str)
        {
            size_t sz = str.length();
    #if defined(WIN32)
            int nd = WideCharToMultiByte(CP_ACP, 0, &str[0], sz, NULL, 0, NULL, NULL);
            std::string ret(nd, 0);
            int w = WideCharToMultiByte(CP_ACP, 0, &str[0], sz, &ret[0], nd, NULL, NULL);
            /*if (ret.length() != sz) {
                throw std::exception("WStringToString Err");
            }*/
            return ret;
    #else
            const wchar_t* p = str.c_str();
            char* tp = new char[sz];
            size_t w = wcstombs(tp, p, sz);
            if (w != sz) {
                delete[] tp;
    
                throw std::exception("WStringToString Err");
            }
            std::string ret(tp);
            delete[] tp;
            return ret;
    #endif
        }
    
        std::string getexepath()
        {
            wchar_t result[MAX_PATH];
    
            std::wstring wstr = std::wstring(result, GetModuleFileName(NULL, result, MAX_PATH));
            return WStringToString(wstr);
        }
    
    
        inline BOOL IsDataSectionNeeded(const WCHAR* pModuleName)
        {
            if (pModuleName == 0)
            {
                return FALSE;
            }
    
            WCHAR szFileName[_MAX_FNAME] = L"";
            _wsplitpath(pModuleName, NULL, NULL, szFileName, NULL);
    
            if (_wcsicmp(szFileName, std::wstring(L"ntdll").c_str()) == 0)
                return TRUE;
    
            return FALSE;
        }
    
        inline BOOL CALLBACK MiniDumpCallback(PVOID                            pParam,
            const PMINIDUMP_CALLBACK_INPUT   pInput,
            PMINIDUMP_CALLBACK_OUTPUT        pOutput)
        {
            if (pInput == 0 || pOutput == 0)
                return FALSE;
    
            switch (pInput->CallbackType)
            {
            case ModuleCallback:
                if (pOutput->ModuleWriteFlags & ModuleWriteDataSeg)
                    if (!IsDataSectionNeeded(pInput->Module.FullPath))
                        pOutput->ModuleWriteFlags &= (~ModuleWriteDataSeg);
            case IncludeModuleCallback:
            case IncludeThreadCallback:
            case ThreadCallback:
            case ThreadExCallback:
                return TRUE;
            default:;
            }
    
            return FALSE;
        }
    
        inline void CreateMiniDump(PEXCEPTION_POINTERS pep, LPCTSTR strFileName)
        {
    
    
            HANDLE hFile = CreateFile(strFileName, GENERIC_READ | GENERIC_WRITE,
                FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    
            if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE))
            {
                MINIDUMP_EXCEPTION_INFORMATION mdei;
                mdei.ThreadId = GetCurrentThreadId();
                mdei.ExceptionPointers = pep;
                mdei.ClientPointers = NULL;
    
                MINIDUMP_CALLBACK_INFORMATION mci;
                mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE)MiniDumpCallback;
                mci.CallbackParam = 0;
    
                ::MiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), hFile, MiniDumpNormal, (pep != 0) ? &mdei : 0, NULL, &mci);
    
                CloseHandle(hFile);
            }
        }
    
    
        LONG __stdcall MyUnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
        {
            std::string exename = "Dmp";
            std::wstring wexename = StringToWString(exename);;
            std::wstring filename = wexename + L"-" + GetTimeNowString() + L".dmp";
            CreateMiniDump(pExceptionInfo, filename.c_str());
    
            return EXCEPTION_EXECUTE_HANDLER;
        }
    
        // 此函数一旦成功调用,之后对 SetUnhandledExceptionFilter 的调用将无效
        void DisableSetUnhandledExceptionFilter()
        {
            void* addr = (void*)GetProcAddress(LoadLibrary(L"kernel32.dll"),
                "SetUnhandledExceptionFilter");
    
            if (addr)
            {
                unsigned char code[16];
                int size = 0;
    
                code[size++] = 0x33;
                code[size++] = 0xC0;
                code[size++] = 0xC2;
                code[size++] = 0x04;
                code[size++] = 0x00;
    
                DWORD dwOldFlag, dwTempFlag;
                VirtualProtect(addr, size, PAGE_READWRITE, &dwOldFlag);
                WriteProcessMemory(GetCurrentProcess(), addr, code, size, NULL);
                VirtualProtect(addr, size, dwOldFlag, &dwTempFlag);
            }
        }
    
        void InitMinDump()
        {
            //注册异常处理函数
            SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
    
            //使SetUnhandledExceptionFilter
            DisableSetUnhandledExceptionFilter();
        }
    }

    使用:

    int main()
    {
      ......
        FrameworkMiniDump::InitMinDump(); 
      ......  
    }

    调用一下InitMinDump就可以了,这里面会注册一个回调,崩溃时会保存的dmp文件。

    注意:需要在debug模式。保存下来的dmp文件,需要结合pdb文件和源代码才能定位到哪里崩溃了。具体的我也不懂。

  • 相关阅读:
    sqlserver把小数点后面多余的0去掉
    C#使用Linq对DataGridView进行模糊查找
    winform dataGridView DataGridViewComboBoxColumn 下拉框事件
    JGit与远程仓库链接使用的两种验证方式(ssh和https)
    Quartz不用配置文件配置启动
    SpringBoot之退出服务(exit)时调用自定义的销毁方法
    Java注解Annotation
    Java自定义数据验证注解Annotation
    我的ehcache笔记
    Java中泛型Class<T>、T与Class<?>
  • 原文地址:https://www.cnblogs.com/xcywt/p/10291219.html
Copyright © 2020-2023  润新知