zoukankan      html  css  js  c++  java
  • 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文件和源代码才能定位到哪里崩溃了。具体的我也不懂。

  • 相关阅读:
    多表联合查询,利用 concat 模糊搜索
    order by 中利用 case when 排序
    Quartz.NET 3.0.7 + MySql 动态调度作业+动态切换版本+多作业引用同一程序集不同版本+持久化+集群(一)
    ASP.NET Core 2.2 基础知识(十八) 托管和部署 概述
    ASP.NET Core 2.2 基础知识(十七) SignalR 一个极其简陋的聊天室
    ASP.NET Core 2.2 基础知识(十六) SignalR 概述
    ASP.NET Core 2.2 基础知识(十五) Swagger
    ASP.NET Core 2.2 基础知识(十四) WebAPI Action返回类型(未完待续)
    linux磁盘管理 磁盘查看操作
    linux磁盘管理 文件挂载
  • 原文地址:https://www.cnblogs.com/xcywt/p/10291219.html
Copyright © 2011-2022 走看看