欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

找到Qt程序长时间运行崩溃原因的方法--Dump(DMP)文件

程序员文章站 2022-06-16 16:18:23
...

  最近遇到一个问题,使用vs+Qt开发应用程序,在本地测试正常,但在别人的机器上(windows平台)运行了一段时间(大概五天)崩溃了。所以这个时候我们应该怎样调试并找到程序崩溃的原因呢?发布的应用程序使用的是release版本。release版本是比较难调试的,因为缺少很多调试信息,在VC/VS中我们可以通过生成DMP + PDB进行源码级定位,使用这种方法,当程序在别人电脑上出现异常或者崩溃的时候,会生成DMP文件,然后把该文件拷贝到自己的开发机器上,配合pdb文件调试就可以找到错误的位置,直接把问题定位到源代码中的位置。

  本文参考了其它博主的博客,比如:

《vs2010 利用DMP文件、pdb文件查找release下的异常行号的方法》https://blog.csdn.net/itworld123/article/details/79041500

《让程序在崩溃时体面的退出之Dump文件》https://blog.csdn.net/starlee/article/details/6630816

感谢这两位博主的博客,本文在这两篇博客的基础上将代码作了一点改动,使得vs+Qt开发windows应用程序一样可以使用这种方法进行定位调试。下面以开发环境为win7+vs2015+Qt5.9.0为例,介绍这个方法:

一、代码

  使用vs(演示用的是vs2015)创建一个Qt工程,往工程里添加main.cpp、dmp3b.cpp、dmp3b.h三个文件。三个文件的代码分别如下图所示:

main.cpp

#include "dmp3b.h"
#include <QtWidgets/QApplication>
#include <windows.h>
#include <DbgHelp.h>
#pragma comment(lib,"Dbghelp.lib")

long  __stdcall CrashInfocallback(_EXCEPTION_POINTERS *pexcp)
{
	//创建 Dump 文件
	HANDLE hDumpFile = ::CreateFile(
		L"MEMORY.DMP",
		GENERIC_WRITE,
		0,
		NULL,
		CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL,
		NULL
	);
	if (hDumpFile != INVALID_HANDLE_VALUE)
	{
		//Dump信息
		MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
		dumpInfo.ExceptionPointers = pexcp;
		dumpInfo.ThreadId = GetCurrentThreadId();
		dumpInfo.ClientPointers = TRUE;
		//写入Dump文件内容
		::MiniDumpWriteDump(
			GetCurrentProcess(),
			GetCurrentProcessId(),
			hDumpFile,
			MiniDumpNormal,
			&dumpInfo,
			NULL,
			NULL
		);
	}
	return 0;
}

int main(int argc, char *argv[])
{
	::SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)CrashInfocallback);
	QApplication a(argc, argv);
	DMP3B w;
	//w.show();
	return a.exec();
}

 

dmp3b.cpp

#include "dmp3b.h"
#include <QThread>

class CrashTest
{
public:
	void Test()
	{
		Crash();
	}

private:
	void Crash()
	{
		int i = 13;
		int j = 0;
		int m = i / j;
		printf("m=%d\n", m);
	}
};

DMP3B::DMP3B(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);
	this->show();
	QThread::msleep(5000);
	CrashTest test;
	test.Test();
}

 

dmp3b.h

#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_dmp3b.h"

class DMP3B : public QMainWindow
{
	Q_OBJECT

public:
	DMP3B(QWidget *parent = Q_NULLPTR);

private:
	Ui::DMP3BClass ui;
};

 

二、运行效果

  将上述代码在vs编译,运行。界面上会出现一个窗口,5秒后,由于执行了语句int m = i / j; (j的值为0)程序会崩溃,如下图所示,然后工程目录下(或者exe文件所在目录下)会出现一个MEMORY.DMP文件。

找到Qt程序长时间运行崩溃原因的方法--Dump(DMP)文件

 

三、使用DMP文件调试,定位找到崩溃原因

  将DMP文件复制到自己开发用的电脑对应的exe文件和pdb文件所在的目录下,如下图所示:

找到Qt程序长时间运行崩溃原因的方法--Dump(DMP)文件

 

鼠标左键双击DMP文件,如果电脑上装了vs,则会出现下图页面:

找到Qt程序长时间运行崩溃原因的方法--Dump(DMP)文件

 

鼠标左键单击“使用仅限本机进行调试”。可以看到如下图所示,定位到语句int m = i/j;找到程序崩溃的问题。

找到Qt程序长时间运行崩溃原因的方法--Dump(DMP)文件

 

四、vs的设置

  要想实现上述功能,首先vs得经过一些设置,否则可能无法正常生成或者使用DMP文件。

(一):属性页->链接器->调试->生成调试信息,这里得选true(默认值是false),如下图所示。如果没有选true,可能不会生成pdb文件

找到Qt程序长时间运行崩溃原因的方法--Dump(DMP)文件

 

(二):属性页->C/C++->常规->调试信息格式,这里得选“程序数据库(/Zi)”,如下图所示。否则双击打开DMP文件时,可能会显示“无可用源,此模块的调试信息中缺少源信息”,无法定位到源代码中的错误。

找到Qt程序长时间运行崩溃原因的方法--Dump(DMP)文件

 

(三):属性页->C/C++->优化->优化,这里得选“已禁用(/Od)”,如下图所示。否则双击打开DMP文件时,可能无法准确定位错误,或者定位到错误所在的函数外面

找到Qt程序长时间运行崩溃原因的方法--Dump(DMP)文件

 

五、其它注意事项

  (一)使用DMP文件和pdb文件调试时DMP、exe和pdb三个文件要保持版本一致。也就是说,如果你运行exe文件,程序崩溃,生成DMP文件后,此时你再重新编译程序,重新生成了exe文件和pdb文件。即使源码没有发生任何改动,你双击DMP文件也是没有办法再定位到源代码中的错误了。所以你得及时把exe文件和pdb文件做好备份。

  (二)有些时候即使程序崩溃了也是没有办法生成DMP文件的,比如有时数组越界导致程序崩溃的时候。所以这个方法也不能保证一定能找到程序崩溃的原因,所以大家得掌握更多的调试手段。

 

六、总结

  windows平台下生成DMP文件是一种很重要的调试方法,可以帮助我们更好更快地定位程序崩溃的问题。

相关标签: Qt DMP dump