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文件生成与分析


 


目录
打赏
0
0
0
0
23
分享
相关文章
玩转C++内存管理:从新手到高手的必备指南
C++中的内存管理是编写高效、可靠程序的关键所在。C++不仅继承了C语言的内存管理方式,还增加了面向对象的内存分配机制,使得内存管理既有灵活性,也更加复杂。学习内存管理不仅有助于提升程序效率,还有助于理解计算机的工作原理和资源分配策略。
C++/C的内存管理
本文主要讲解C++/C中的程序区域划分与内存管理方式。首先介绍程序区域,包括栈(存储局部变量等,向下增长)、堆(动态内存分配,向上分配)、数据段(存储静态和全局变量)及代码段(存放可执行代码)。接着探讨C++内存管理,new/delete操作符相比C语言的malloc/free更强大,支持对象构造与析构。还深入解析了new/delete的实现原理、定位new表达式以及二者与malloc/free的区别。最后附上一句鸡汤激励大家行动缓解焦虑。
|
24天前
|
课时4:对象内存分析
接下来对对象实例化操作展开初步分析。在整个课程学习中,对象使用环节往往是最棘手的问题所在。
go的内存逃逸分析
内存逃逸分析是Go编译器在编译期间根据变量的类型和作用域,确定变量分配在堆上还是栈上的过程。如果变量需要分配在堆上,则称作内存逃逸。Go语言有自动内存管理(GC),开发者无需手动释放内存,但编译器需准确分配内存以优化性能。常见的内存逃逸场景包括返回局部变量的指针、使用`interface{}`动态类型、栈空间不足和闭包等。内存逃逸会影响性能,因为操作堆比栈慢,且增加GC压力。合理使用内存逃逸分析工具(如`-gcflags=-m`)有助于编写高效代码。
【硬核】C++11并发:内存模型和原子类型
本文从C++11并发编程中的关键概念——内存模型与原子类型入手,结合详尽的代码示例,抽丝剥茧地介绍了如何实现无锁化并发的性能优化。
219 68
彻底摘明白 C++ 的动态内存分配原理
大家好,我是V哥。C++的动态内存分配允许程序在运行时请求和释放内存,主要通过`new`/`delete`(用于对象)及`malloc`/`calloc`/`realloc`/`free`(继承自C语言)实现。`new`分配并初始化对象内存,`delete`释放并调用析构函数;而`malloc`等函数仅处理裸内存,不涉及构造与析构。掌握这些可有效管理内存,避免泄漏和悬空指针问题。智能指针如`std::unique_ptr`和`std::shared_ptr`能自动管理内存,确保异常安全。关注威哥爱编程,了解更多全栈开发技巧。 先赞再看后评论,腰缠万贯财进门。
125 0
|
4月前
|
如何使用内存快照分析工具来分析Node.js应用的内存问题?
需要注意的是,不同的内存快照分析工具可能具有不同的功能和操作方式,在使用时需要根据具体工具的说明和特点进行灵活运用。
165 62
基于哈希表的文件共享平台 C++ 算法实现与分析
在数字化时代,文件共享平台不可或缺。本文探讨哈希表在文件共享中的应用,包括原理、优势及C++实现。哈希表通过键值对快速访问文件元数据(如文件名、大小、位置等),查找时间复杂度为O(1),显著提升查找速度和用户体验。代码示例展示了文件上传和搜索功能,实际应用中需解决哈希冲突、动态扩容和线程安全等问题,以优化性能。
什么是内存泄漏?C++中如何检测和解决?
大家好,我是V哥。内存泄露是编程中的常见问题,可能导致程序崩溃。特别是在金三银四跳槽季,面试官常问此问题。本文将探讨内存泄露的定义、危害、检测方法及解决策略,帮助你掌握这一关键知识点。通过学习如何正确管理内存、使用智能指针和RAII原则,避免内存泄露,提升代码健壮性。同时,了解常见的内存泄露场景,如忘记释放内存、异常处理不当等,确保在面试中不被秒杀。最后,预祝大家新的一年工作顺利,涨薪多多!关注威哥爱编程,一起成为更好的程序员。
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
114 1