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月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
76 1
|
2月前
|
JavaScript
如何使用内存快照分析工具来分析Node.js应用的内存问题?
需要注意的是,不同的内存快照分析工具可能具有不同的功能和操作方式,在使用时需要根据具体工具的说明和特点进行灵活运用。
56 3
|
2月前
|
开发框架 监控 .NET
【Azure App Service】部署在App Service上的.NET应用内存消耗不能超过2GB的情况分析
x64 dotnet runtime is not installed on the app service by default. Since we had the app service running in x64, it was proxying the request to a 32 bit dotnet process which was throwing an OutOfMemoryException with requests >100MB. It worked on the IaaS servers because we had the x64 runtime install
|
2月前
|
存储 缓存 Java
结构体和类在内存管理方面的差异对程序性能有何影响?
【10月更文挑战第30天】结构体和类在内存管理方面的差异对程序性能有着重要的影响。在实际编程中,需要根据具体的应用场景和性能要求,合理地选择使用结构体或类,以优化程序的性能和内存使用效率。
|
2月前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
446 1
|
1月前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
2月前
|
Java
JVM内存参数
-Xmx[]:堆空间最大内存 -Xms[]:堆空间最小内存,一般设置成跟堆空间最大内存一样的 -Xmn[]:新生代的最大内存 -xx[use 垃圾回收器名称]:指定垃圾回收器 -xss:设置单个线程栈大小 一般设堆空间为最大可用物理地址的百分之80
|
2月前
|
Java
JVM运行时数据区(内存结构)
1)虚拟机栈:每次调用方法都会在虚拟机栈中产生一个栈帧,每个栈帧中都有方法的参数、局部变量、方法出口等信息,方法执行完毕后释放栈帧 (2)本地方法栈:为native修饰的本地方法提供的空间,在HotSpot中与虚拟机合二为一 (3)程序计数器:保存指令执行的地址,方便线程切回后能继续执行代码
27 3
|
2月前
|
存储 缓存 监控
Elasticsearch集群JVM调优堆外内存
Elasticsearch集群JVM调优堆外内存
59 1
|
2月前
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。