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

原文地址:https://www.cnblogs.com/xcywt/p/10291219.html

时间: 2024-10-07 09:59:03

windows生成dump文件的相关文章

使用dbghelp生成dump文件以及事后调试分析

前言 在产品的实际应用环境中,如果我们的程序在客户那里出现了问题,例如程序异常了,而这个时候的现象又不能还原或者很难还原重现,那么只有使用dump文件来保存程序的当前运行信息,例如调用堆栈等,同时使用符号文件来定位问题了;这里主要讲解使用dbghelp库来生成输出dump文件,同时使用符号文件和windbg来分析问题.样例代码 1 #include "stdafx.h" 2 #include <Windows.h> 3 #include <iostream> 4

程序自动生成dump文件

作用 可以再程序崩溃后保留崩溃现场,方便事后查找程序的崩溃原因. 前提是奔溃程序所对应的代码和PDB文件都是匹配的(发布程序的时候,保留源代码和PDB文件). 代码示例 原理是使用DbgHelp的自定义未处理异常来保留崩溃现场到文件的,使用直接包含该头文件,然后再main函数的开始就调用EnableAutoDump函数. // pro_dump.h // 包含本文件是用来处理程序崩溃时自动生成dump文件的 // 生成的dump文件在程序的工作目录下 // 文件名格式是:年月日_时分秒.dmp

程序自动生成Dump文件()

前言:通过drwtsn32.NTSD.CDB等调试工具生成Dump文件, drwtsn32存在的缺点虽然NTSD.CDB可以完全解决,但并不是所有的操作系统中都安装了NTSD.CDB等调试工具.了解了mini dump文件格式后,完全可以程序自动生成Dump文件. 本文主要讨论以下内容: 1.  运行原理 2.  程序修改 3.  注意事项 一.   运行原理 当程序遇到未处理异常(主要指非指针造成)导致程序崩溃死,如果在异常发生之前调用了SetUnhandledExceptionFilter(

调试SQLSERVER (一)生成dump文件的方法

调试SQLSERVER (一)生成dump文件的方法 调试SQLSERVER (二)使用Windbg调试SQLSERVER的环境设置调试SQLSERVER (三)使用Windbg调试SQLSERVER的一些命令 我们知道调试程序主要有两种方法 一种是:live debugging (附加进程 使进程hang住) 生产环境最好不要live debugging 一种是:post-mortem debugging or reading dump files (生成dump文件然后进行分析) 现在介绍一

如何设置C++崩溃时生成Dump文件

Dump 文件是进程的内存镜像 , 可以把程序的执行状态通过调试器保存到dump文件中 ; Dump 文件是用来给驱动程序编写人员调试驱动程序用的 , 这种文件必须用专用工具软件打开 , 比如使用 WinDbg , VisualStudio 打开 ; 当我们的程序发布出去之后 , 在客户机上是无法跟踪自己代码的 BUG 的 , 所以 Dump 文件对于我们来说特别有用 ; 我们可以通过 .dmp 文件把出现 BUG 的情况再现 , 然后再现客户环境 (包括堆栈调用等情况) , 设置源码调试路径

WinDBG 技巧:如何生成Dump 文件(.dump 命令)

程序崩溃(crash)的时候, 为了以后能够调试分析问题, 可以使用WinDBG要把当时程序内存空间数据都保存下来,生成的文件称为dump 文件. 步骤: 1) 打开WinDBG并将之Attach 到crash的程序进程 2) 输入产生dump 文件的命令 WinDBG产生dump 文件的命令是 .dump ,可以选择不同的参数来生成不同类型的dump文件. 选项(1): /m 命令行示例:.dump /m C:\dumps\myapp.dmp 注解: 缺省选项,生成标准的minidump, 转

JVM 在遇到OOM(OutOfMemoryError)时生成Dump文件的三种方式

JVM 在遇到OOM(OutOfMemoryError)时生成Dump文件的三种方式,以及如何使用Eclips Memory Analyzer(MAT)插件进行堆内存分析. 方法一: jmap -dump:format=b,file=文件名 [pid] 例如: jmap -dump:format=b,file=/usr/local/base/02.hprof 12942 方法二: 让JVM在遇到OOM(OutOfMemoryError)时生成Dump文件,需要配置一些信息 -XX:+HeapDu

JVM生成dump文件方式

JVM生成dump文件一般有两种方式 一. 出现OOM时自动生成堆dumpJVM启动命令增加两个参数:-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/home/app/dumps/ 二.人工通过执行指令,直接生成当前JVM的dump文件例如:jmap -dump:format=b,file=/home/app/testdump.hprof 6218其中6218是JVM的当前进程号 原文地址:https://www.cnblogs.com/xing

Windows下生成dump文件方法

[转载请注明出处]:http://blog.csdn.net/longlong530 一. 背景 没人能保证自己的软件在各种未知环境运行下,会木有任何问题.那么如果程序崩溃了怎么办?看日志?日志不全又怎么办?日志能帮你定位的多细致呢?如果能有种方法记录程序最后工作的状态,比如堆栈调用情况等,那么我们就可以获悉"它是如何挂掉的~" 二. 调研 我们对程序bug引起的程序崩溃的五种定位方法进行了调研,并最终选择方案5为我所在项目使用的程序崩溃定位方案. 方案1: 崩溃地址 + MAP文件