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

最近遇到一个问题,使用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;
};
 

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;
};
 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值