dump系列(2)C++程序异常或内存错误,导致闪退的解决办法:分析dump文件

简介: dump系列(2)C++程序异常或内存错误,导致闪退的解决办法:分析dump文件

如何在发布后程序中捕获程序的崩溃和异常往往是比较麻烦的事情,一般采用日志记录的方法来记录程序运行的每个流程,但是通常为了程序运行的性能,日志记录的方法只是记录程序运行的每个主要的处理流程,不能进行具体详细的记录,比如for 循环中的崩溃记录。C++语言中调用window API函数CreateFile()和MiniDumpWriteDump(),可以方便的记录程序崩溃时的Dump信息,并保持dump文件,根据dump文件对应的源码工程和.pdb文件,我们就可以快速的定位到程序崩溃的源码位置,极大的提高了调试代码的效率。然而,Dump记录程序崩溃的方法不是万能的,有时候一些数组越界、容器访问异常等致命的问题,也不一定能准确的记录下来。总之,Dump文件记录程序崩溃的方法是开放人员常用的方法,并且能捕获大多数的程序崩溃问题。


1、程序中加入存储Dump的代码


通过SetUnhandledExceptionFilter设置捕获dump的入口,然后通过MiniDumpWriteDump生成dump文件。


头文件dump.h

#pragma once
#define SOFTWARE_VERSION      _T("V1.0.202001")
int GenerateMiniDump(PEXCEPTION_POINTERS pExceptionPointers);
LONG ApplicationCrashHandler(LPEXCEPTION_POINTERS lpExceptionInfo);


源文件dump.cpp

#include "stdafx.h"
#include "dump.h"
#include <Windows.h>
#include <DbgHelp.h>
//需要用到文件dbghelp.dll,可以从以下路径拷贝
//C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TestWindow\Extensions\Cpp\dbghelp.dll
//C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TestWindow\Extensions\Cpp\x64\dbghelp.dll
// 创建Dump文件
int GenerateMiniDump(PEXCEPTION_POINTERS pExceptionPointers)
{
  // 定义函数指针
  typedef BOOL(WINAPI * MiniDumpWriteDumpT)(
    HANDLE,
    DWORD,
    HANDLE,
    MINIDUMP_TYPE,
    PMINIDUMP_EXCEPTION_INFORMATION,
    PMINIDUMP_USER_STREAM_INFORMATION,
    PMINIDUMP_CALLBACK_INFORMATION
    );
  // 从"DbgHelp.dll"库中获取"MiniDumpWriteDump"函数
  MiniDumpWriteDumpT pfnMiniDumpWriteDump = NULL;
  HMODULE hDbgHelp = LoadLibrary(L"dbghelp.dll");
  if (NULL == hDbgHelp)
  {
    return EXCEPTION_CONTINUE_EXECUTION;
  }
  pfnMiniDumpWriteDump = (MiniDumpWriteDumpT)GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
  if (NULL == pfnMiniDumpWriteDump)
  {
    FreeLibrary(hDbgHelp);
    return EXCEPTION_CONTINUE_EXECUTION;
  }
  // 创建dmp文件
  TCHAR szFileName[MAX_PATH] = { 0 };
  TCHAR* szVersion = SOFTWARE_VERSION;
  SYSTEMTIME stLocalTime;
  GetLocalTime(&stLocalTime);
  wsprintf(szFileName, L"%04d%02d%02d_%02d%02d%02d_%s.dmp",
    stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
    stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, szVersion);
  HANDLE hDumpFile = CreateFile(szFileName, GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
  if (INVALID_HANDLE_VALUE == hDumpFile)
  {
    FreeLibrary(hDbgHelp);
    return EXCEPTION_CONTINUE_EXECUTION;
  }
  // 写入dmp文件
  MINIDUMP_EXCEPTION_INFORMATION expParam;
  expParam.ThreadId = GetCurrentThreadId();
  expParam.ExceptionPointers = pExceptionPointers;
  expParam.ClientPointers = FALSE;
  pfnMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
    hDumpFile, MiniDumpWithDataSegs, (pExceptionPointers ? &expParam : NULL), NULL, NULL);
  // 释放文件
  CloseHandle(hDumpFile);
  FreeLibrary(hDbgHelp);
  return EXCEPTION_EXECUTE_HANDLER;
}
// 处理Unhandled Exception的回调函数
LONG ApplicationCrashHandler(LPEXCEPTION_POINTERS lpExceptionInfo)
{
  // 这里做一些异常的过滤或提示
  if (IsDebuggerPresent())
  {
    return EXCEPTION_CONTINUE_SEARCH;
  }
  return GenerateMiniDump(lpExceptionInfo);
}

举例MFC项目程序,在app入口添加SetUnhandledExceptionFilter


#include "stdafx.h"
#include "dump.h"
BOOL CSmartDispenserApp::InitInstance()
{
    //加入崩溃自动记录dump文件功能
    SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);
    ...
}


2、如何分析dump文件?


详情参见我的另一篇博文《Windows下dump文件生成与分析


 


相关文章
|
2月前
|
安全 Linux Shell
Linux上执行内存中的脚本和程序
【9月更文挑战第3天】在 Linux 系统中,可以通过多种方式执行内存中的脚本和程序:一是使用 `eval` 命令直接执行内存中的脚本内容;二是利用管道将脚本内容传递给 `bash` 解释器执行;三是将编译好的程序复制到 `/dev/shm` 并执行。这些方法虽便捷,但也需谨慎操作以避免安全风险。
179 6
|
26天前
|
NoSQL 测试技术
内存程序崩溃
【10月更文挑战第13天】
129 62
|
14天前
|
存储 缓存 Java
结构体和类在内存管理方面的差异对程序性能有何影响?
【10月更文挑战第30天】结构体和类在内存管理方面的差异对程序性能有着重要的影响。在实际编程中,需要根据具体的应用场景和性能要求,合理地选择使用结构体或类,以优化程序的性能和内存使用效率。
|
1月前
|
存储 程序员 编译器
简述 C、C++程序编译的内存分配情况
在C和C++程序编译过程中,内存被划分为几个区域进行分配:代码区存储常量和执行指令;全局/静态变量区存放全局变量及静态变量;栈区管理函数参数、局部变量等;堆区则用于动态分配内存,由程序员控制释放,共同支撑着程序运行时的数据存储与处理需求。
105 21
|
2月前
|
C语言 Android开发 C++
基于MTuner软件进行qt的mingw编译程序的内存泄漏检测
本文介绍了使用MTuner软件进行Qt MinGW编译程序的内存泄漏检测的方法,提供了MTuner的下载链接和测试代码示例,并通过将Debug程序拖入MTuner来定位内存泄漏问题。
基于MTuner软件进行qt的mingw编译程序的内存泄漏检测
|
2月前
|
C++
【C++基础】程序流程结构详解
这篇文章详细介绍了C++中程序流程的三种基本结构:顺序结构、选择结构和循环结构,包括if语句、三目运算符、switch语句、while循环、do…while循环、for循环以及跳转语句break、continue和goto的使用和示例。
46 2
|
2月前
|
存储 运维
.NET开发必备技巧:使用Visual Studio分析.NET Dump,快速查找程序内存泄漏问题!
.NET开发必备技巧:使用Visual Studio分析.NET Dump,快速查找程序内存泄漏问题!
|
2月前
使用qemu来dump虚拟机的内存,然后用crash来分析
使用qemu来dump虚拟机的内存,然后用crash来分析
|
3月前
|
PHP C++ Python
右手坐标系,空间点绕轴旋转公式&程序(Python和C++程序)
右手坐标系,空间点绕轴旋转公式&程序(Python和C++程序)
64 0
|
9天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
37 4