• 程序自动生成Dump文件()


    前言:通过drwtsn32、NTSD、CDB等调试工具生成Dump文件, drwtsn32存在的缺点虽然NTSD、CDB可以完全解决,但并不是所有的操作系统中都安装了NTSD、CDB等调试工具。了解了mini dump文件格式后,完全可以程序自动生成Dump文件。

    本文主要讨论以下内容:

    1、  运行原理

    2、  程序修改

    3、  注意事项

    一、   运行原理

    当程序遇到未处理异常(主要指非指针造成)导致程序崩溃死,如果在异常发生之前调用了SetUnhandledExceptionFilter()函数,异常交给函数处理。MSDN中描述为:

    Issuing SetUnhandledExceptionFilter replaces the existing top-level exception filter for all existing and all future threads in the calling process.

    因而,在程序开始处增加SetUnhandledExceptionFilter()函数,并在函数中利用适当的方法生成Dump文件,即可实现需要的功能。

    二、   程序修改

    1、  重载 << 操作符。(本步可以不实现)

    std::ostream& operator<<(std::ostream& os, const EXCEPTION_RECORD& red)

    {

    return os << "   Thread ID:" << GetCurrentThreadId()

    << "   ExceptionCode: " << red.ExceptionCode << "/n"

    << "   ExceptionFlags: " << red.ExceptionFlags << "/n"

    << "   ExceptionAddress: " << red.ExceptionAddress << "/n"

    << "   NumberParameters: " << red.NumberParameters;

    }

             

    2、  实现UnhandledExceptionFilter

    #include "minidmp.h"

    LONG WINAPI GPTUnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)

    {

    CreateMiniDump(pExceptionInfo, L"Exception.dmp");

                  std::cerr << "未知错误:" << (*pExceptionInfo->ExceptionRecord) << std::endl;

                  exit(pExceptionInfo->ExceptionRecord->ExceptionCode);

                 

                  return EXCEPTION_EXECUTE_HANDLER;    // 程序停止运行

    }

    3、  在异常发生之前调用SetUnhandledExceptionFilter(GPTUnhandledExceptionFilter);

    通常在Main()函数开始时调用即可。

    4、  CreateMiniDump()函数在minidmp.h头文件中定义,文件如下:

    #pragma once

    #include <windows.h>

    #include <imagehlp.h>

    #include <stdlib.h>

    #pragma comment(lib, "dbghelp.lib")

     

    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, L"ntdll") == 0)

           return TRUE;

     

      return FALSE;

    }

     

    inline BOOL CALLBACK MiniDumpCallback(PVOID                            pParam,

                                              constPMINIDUMP_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(EXCEPTION_POINTERS* pep, LPCTSTR strFileName)

    {

      HANDLE hFile = CreateFile(strFileName, GENERIC_READ | GENERIC_WRITE,

           0, 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     = FALSE;

           MINIDUMP_CALLBACK_INFORMATION mci;

           mci.CallbackRoutine     = (MINIDUMP_CALLBACK_ROUTINE)MiniDumpCallback;

           mci.CallbackParam       = 0;

           MINIDUMP_TYPE mdt       = (MINIDUMP_TYPE)(MiniDumpWithPrivateReadWriteMemory |

                MiniDumpWithDataSegs |

                MiniDumpWithHandleData |

                0x00000800 /*MiniDumpWithFullMemoryInfo*/ |

                0x00001000 /*MiniDumpWithThreadInfo*/ |

                MiniDumpWithUnloadedModules);

           MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),

                hFile, mdt, (pep != 0) ? &mdei : 0, 0, &mci);

     

           CloseHandle(hFile);

      }

    }

    三、   注意事项

    1、  可执行文件(exe)必须找到dbghelp.dll,才能生成Dump文件。这个DLL可以从调试工具包中找到。

    2、  当异常代码定位成功以后,如果无法阻止异常的产生,可以用 __try 结构包装异常代码,__try 和 try 不同,前者可以捕获非法指针产生的异常。

    __try {

    // 会异常的函数

    }

    __except( EXCEPTION_EXECUTE_HANDLER ){

    // 异常处理

    }

    参考文档:

    http://blog.csdn.net/ArCoolGG/archive/2007/04/05/1553027.aspx

    http://www.debuginfo.com/articles/effminidumps.html

    http://blog.csdn.net/jiangxinyu/article/details/5348770

  • 相关阅读:
    C语言实现链表
    获取两个数之间的随机数-java
    C#继承机制 多级继承
    C#继承机制 访问与隐藏基类成员
    C#继承机制 C#中的继承符合下列规则
    C#装箱与拆箱的研究
    C#箴言之用属性来访问类的私有成员
    C# 创建和初始化集合对象
    C# 常用函数和方法集汇总
    C# 多态与new关键字
  • 原文地址:https://www.cnblogs.com/findumars/p/5811637.html
Copyright © 2020-2023  润新知