一 引言

我们写代码的时候经常会遇到一些Bug导致程序异常退出,比如访问了空指针。在大多数情况下,我们能够根据经验和IDE本身提供的调试功能来定位问题,并找到解决方案。但最近在工作中遇到了一个问题,一个提供后台服务的程序在运行不等时间后例如30分钟,一个小时或其它时间后会异常退出。一时,毫无头绪,因为代码里面嵌入了其它同事写的模块,虽然很怀疑是同事引起的,但是没有证据就没有底气啊。百度了很多解决办法后,最终选择下面的方案,最终证明是同事模块引起的。 以下内容是我整理网友的解决方案,加以自己的简单封装,下面就对这种利用Dump文件进行程序异常分析的方式进行简介。

二 Dump文件

来自百度百科:

Dump文件是进程的内存镜像。可以把程序的执行状态通过调试器保存到dump文件中。Dump文件是用来给驱动程序编写人员调试驱动程序用的,这种文件必须用专用工具软件打开,比如使用WinDbg打开。

我的解释:dump文件可以保存程序的运行信息,Windows下程序奔溃退出后会调用一个被注册过的处理函数,我们就可以在这个函数里面生成dump文件,保存现场,然后利用WinDbg Preview进行分析,可以查看当时调用堆栈,确定程序最后调用了哪个函数导致了没有出来,引起程序异常崩溃。

三 如何在程序崩溃时生成Dump文件

SetUnhandledExceptionFilter函数是Win32API的异常捕获函数,在程式异常结束前。会调用该函数注冊的回调函数,这样就能在进程终止前运行指定的代码,达到比如保存数据的功能。其实在程序奔溃时我们也可以给予一个用户提示等,下面写出我简单封装的一个类WinDebug,使用的时候调用install即可,该类在程序崩溃时会在当前目录生成Debug.dmp,如果需要其它功能用户可自行更改handler函数。使用时不要忘记链接DbgHelp.lib!!!

WinDebug.h:

#pragma once#include <Windows.h>
#include <DbgHelp.h>class WinDebug
{
public:static void install();private:static long handler(_EXCEPTION_POINTERS* pException);
};

WinDebug.cpp:

#include "WinDebug.h"
#include <QDebug>void WinDebug::install()
{SetUnhandledExceptionFilter(&WinDebug::handler);
}long WinDebug::handler(_EXCEPTION_POINTERS* pException)
{HANDLE hDumpFile = CreateFile(L"Debug.dmp", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);if (hDumpFile != INVALID_HANDLE_VALUE){MINIDUMP_EXCEPTION_INFORMATION dumpInfo;dumpInfo.ExceptionPointers = pException;dumpInfo.ThreadId = GetCurrentThreadId();dumpInfo.ClientPointers = true;MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);}return EXCEPTION_EXECUTE_HANDLER;
}

main.cpp:

#include <QApplication>
#include "WinDebug.h"
#include "mainwindow.h"
#include <QPainter>int main(int argc, char *argv[])
{QApplication a(argc, argv);WinDebug::install();QPainter* p;p->drawLine(0, 0, 100, 100);MainWindow w;w.show();return a.exec();
}

注意:p是空指针,程序会异常退出。

四 Pdb文件

PDB文件是在编译工程的时候产生的,它是和对应的模块(exe或dll)一起生成出来的。pdb文件可以使用一些特有的pdb阅读器打开。如果想把PDB文件转换成TXT文件查看,可以使用专用转换器转换。如果想根据dump文件分析程序是在哪一行崩溃的就必须要有pdb文件,debug下会自动生成pdb文件。那么Release程序如何生成pdb文件呢?Qt工程可以在pro文件中加上

QMAKE_LFLAGS_RELEASE = /INCREMENTAL:NO /DEBUG

VS工程做如下设置:

1.

2.

这样就能在Release下生成PDB文件了。

五 利用WinDbg Preview分析dump文件

WinDbg Preview可以在微软的应用商店和官网下载,这里不再赘述。请自行下载安装!

1.打开WinDbg Preview,界面如下

2.加载dump文件,点击文件,然后点击Open dump file,加载进去刚刚生成的Debug.dmp

3. 设置pdb和源码路径,点击文件->Settings,选择Debugging settings,设置好source path 和 symbol path(pdb文件路径)

4.此时主界面如下:

5. 输入 !analyze -v 或者点击上面的提示,此时会加载一些信息并打印出分析结果,查看STACK_TEXT即可查看程序异常退出前的堆栈信息。

6.我们可以看到上述函数调用过程,最后进去了QPainter::drawLines,这和我们预期的是一致的,这个函数导致了程序崩溃。

五 写在最后

以上只是简单的程序崩溃处理,如果有更加方便简洁的方式也请各位同仁不吝赐教,最后也是感谢网友的无私分享,方有我这篇拙作。


四时最好是三月,一去不回唯少年。

如何定位导致程序异常退出的Bug?相关推荐

  1. linux下怎么查看程序异常,如何检测、定位linux程序异常

    作为linux开发,在工作中或者面试的时候经常会遇到怎么检测程序异常的问题,下面对此作一个总结. 0. 查看程序日志.项目更新日志,发现可疑的地方 使用linux查看内存cpu指令,top.ps初步看 ...

  2. 【C++ linux】SIGPIPE信号在网络通信程序导致程序异常中断

    在网络通信的程序中,忽略SIGPIPE信号,防止程序异常退出 具体原因: 如果send到一个已关闭的socket上,内核就会发出SIGPIPE信号.这个信号   的缺省处理方法是终止进程,大多数时候这 ...

  3. 安卓软件错误log_Android编程实现捕获程序异常退出时的错误log信息功能详解

    本文实例讲述了Android编程实现捕获程序异常退出时的错误log信息功能.分享给大家供大家参考,具体如下: 很多时候我们程序无缘无故的就挂掉了,让我们一头雾水,如果刚好我们在调试,那我们可以通过错误 ...

  4. 如何让程序异常退出后重启

    标 题:如何让程序异常退出后重启 发信人:蔡子楠 出处:http://www.freeeim.com/ 时 间:2008-02-14 11:25:22 "程序 FreeEIM.exe 遇到问 ...

  5. main()如果返回0,则代表程序正常退出,返回非零代表程序异常退出。

    main()如果返回0,则代表程序正常退出,返回非零代表程序异常退出. 参考文章: (1)main()如果返回0,则代表程序正常退出,返回非零代表程序异常退出. (2)https://www.cnbl ...

  6. C#WinForm程序异常退出的捕获、继续执行与自动重启

    C#WinForm程序异常退出的捕获.继续执行与自动重启 参考文章: (1)C#WinForm程序异常退出的捕获.继续执行与自动重启 (2)https://www.cnblogs.com/mq0036 ...

  7. linux进程异常退出分析,ECS Linux程序异常退出提示“out of memory”的临时解决办法...

    ECS Linux上的程序会出现异常退出的情况,退出的原因多数是因为系统内存不足,Linux内存不足通常会触发 Linux 内核里的 Out of Memory (OOM) killer,OOM ki ...

  8. docker-内存不足导致容器异常退出时怎么办

    容器异常退出,通过docker ps -a查看当前容器状态 状态码   描述 0         表示正常退出 非 0       表示异常退出(退出状态码采用 chroot 标准) 125      ...

  9. 没有core的程序异常退出追查过程

    最近朋友项目发生了一件怪事,好好的进程,没有任何痕迹地退出,没有core文件,没有syslog痕迹,也不是进程主动退出,因为逻辑中exit都有日志. 现在记录一下追查过程: 1.先排除core生成条件 ...

最新文章

  1. WM6 Rapi 开发(二) Hello World
  2. C语言 指针 类型的用法大汇总(指针/引用/取值) *与
  3. modbus从站模拟软件_作为工控电气人,你知道我们必备的软件有哪些吗?
  4. 获取repeater控件模版列中的控件
  5. python双向索引什么意思_Python 双向链表的实现
  6. iview select 内存泄漏_Vue遇到的内存泄漏排查处理
  7. sourceTree中git工作流使用
  8. 读书·2018(14本)
  9. 回顾15个月的工作经历
  10. Flutter 项目的闪屏页方案
  11. 局域网常用的几种网络拓扑结构及其特点。
  12. 如何让青少年远离“网络成瘾”?
  13. Centos7.4配置与管理DNS服务器
  14. 信号量和互斥锁的区别
  15. 记录一次对学校考试系统的漏洞挖掘
  16. Day7 String类
  17. QT-----无人机地面站如何修改显示界面1——OpenPilotGCS_config.xml
  18. Tsar学习笔记---tsar tsar2db mysql 集成调测篇
  19. 苹果iOS12.3 Beta2测试固件
  20. 【操作系统】分段存储管理方式

热门文章

  1. 工作文档撰写——产品体验报告
  2. 设备安全:防火墙总结(1)
  3. 定了!今日起,本号粉丝可免费参与网易前端培训营!
  4. GitHub里的灭霸脚本,竟都还不是最奇葩的?
  5. 手绘VS码绘——动态篇(视觉错觉)
  6. 从程序员之死看 IT 人士如何摆脱低情商诅咒——转载自CSDN官方博客
  7. 前端工程师必须知道的网络知识(一)
  8. 搜题公众号制作简单教学
  9. 双十一一大波建站优惠来袭,这不薅点来建站?
  10. java代码混淆 项目加密解决方案 class文件加密 支持JDK16