• windbg调试分析dump工具,使用windbg分析Qt崩溃原因



    在非开发环境,windbg工具可以对.exe可执行文件进行调试,也可以分析dump文件,是release版本运行模式解决bug的神器。

    windbg下载和安装

    一般在安装windows系统软件时会安装windbg,如果没有可以去官网下载:
    windbg下载地址:https://learn.microsoft.com/zh-cn/windows-hardware/drivers/debugger/debugger-download-tools
    选择“用于 Windows (WinDbg) 的调试工具”,点击“Windows SDK”,“download the installer”,下载winsdksetup.exe在线安装,勾选:
    在这里插入图片描述
    安装完成后,开始菜单搜索windbg,启动即可。
    微软官网文档:https://learn.microsoft.com/zh-cn/windows-hardware/drivers/debugger/getting-started-with-windbg

    windbg调试exe可执行文件

    windbg调试依赖.pdb符号文件,调试器需要符号文件来获取有关代码模块的信息(函数名、变量名等)。
    如果使用Qt开发,发布的release版本默认不生成.pdb文件,需要在pro文件添加如下内容:

    QMAKE_LFLAGS_RELEASE += /MAP
    QMAKE_CFLAGS_RELEASE += /Zi
    QMAKE_LFLAGS_RELEASE += /debug /opt:ref
    QMAKE_CXXFLAGS_RELEASE += $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
    QMAKE_LFLAGS_RELEASE += $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO
    LIBS += -lDbgHelp
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在编译release版本时生成.pdb符号文件,注意.pdb文件可能会泄漏源码,不要和exe一起打包发布,在需要调试时再拿过来用。

    本例使用Qt写了一个简单的demo,编译生成可执行文件testDump.exe,运行后崩溃,代码如下:

    void myfuncTest()
    {
        int testNum = 25;
        qDebug() <<"testNum="<<testNum;
    }
    MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        myfuncTest();
        printHelloWorld();
        cptFunc();
    }
    int MainWindow::cptFunc()
    {
        int *pnum = NULL;
        printf("*pnum=%d\n",*pnum);//打印没有分配内存的指针变量,导致crash
        return 0;
    }
    void MainWindow::printHelloWorld()
    {
        qDebug() <<"HelloWorld";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    打包发布后,使用windbg工具,选择菜单栏file-open Executable…,打开“testDump.exe”可执行文件,显示如下内容,包括符号搜索路径,可执行文件依赖库的搜索路径:
    在这里插入图片描述

    几个常用命令:

    .sympath srv*
    查询符号搜索路径。

    .reload
    重新加载符号。

    x testDump!*
    查询可执行文件所有的符号,如果程序较大,符号列表会非常长。

    x testDump!MainWindow::cpt*
    *号是通配符,查询以MainWindow::cpt开头的符号,查询输出:

    0:000> x testDump!MainWindow::cpt*
    00007ff7`ec1310ca testDump!MainWindow::cptFunc =  (inline caller) testDump!MainWindow::MainWindow+4a
    
    
    • 1
    • 2
    • 3

    bm testDump!myfuncTest
    testDump!myfuncTest,在这个符号位置设置断点,输出:

    0:000> bm testDump!myfuncTest
      1: 00007ff6`37a510ca @!"testDump!myfuncTest" (testDump!myfuncTest inlined in testDump!MainWindow::MainWindow+0x4a)
    
    
    
    • 1
    • 2
    • 3
    • 4

    bl
    bl查询断点,输出:

    0:000> bl
         2 e Disable Clear  <inline function>     0001 (0001)  0:**** {testDump!myfuncTest}
             1 e Disable Clear  00007ff6`37a510ca     0001 (0001)  0:**** testDump!MainWindow::MainWindow+0x4a (inline function testDump!myfuncTest)
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    g
    g启动可执行程序,Breakpoint 1 hit命中一个断点,程序停止在断点处。
    k
    k查看堆栈跟踪,代码路径是记录在符号文件里的,如果这个路径有源码,则左侧会自动加载代码;如果路径没有源码,左侧不会弹代码框,但也可以进行调试。
    dv /t
    查看局部变量值,pnum 是空指针,所以打印的时候crash了。

    0:000> dv /t
    int * pnum = 0x00000000`00000000
    
    
    • 1
    • 2
    • 3

    在这里插入图片描述
    ~
    查看进程中所有线程列表。在上述代码中添加一个线程。

    ~0s
    查看编号为0的线程堆栈跟踪,按K查看详细堆栈。
    ~*kv
    ~*kv查看所有线程的调用堆栈。
    在这里插入图片描述
    qd
    退出调试,分离进程。

    windbg分析dump文件

    dump文件是程序崩溃时记录的内存镜像文件,Qt自动生成dump文件的方法参考:Qt崩溃生成内存镜像,windows下生成dump文件,linux下生成core文件
    如果程序运行在远端,不便使用windbg打开exe调试,或者bug不能固定复现,可以设置程序崩溃后自动生成dump文件,发送拷贝到开发环境,使用windbg打开dump分析崩溃原因。

    如果分析失败或没有源码信息,可以尝试设置路径:
    菜单栏,File,Symbol Search Path,设置符号搜索路径,比如srv* C:\dmb*http://msdl.microsoft.com/download/symbols;C:\Users\13770\Desktop\testDump。
    菜单栏,File,Source Search Path,设置源码搜索路径,如果符号文件里记录了源码位置,可不设置。
    菜单栏,File,Executable Image Search Path,设置exe可执行文件路径。

    !analyze -v
    把dmp文件拖到windbg里面自动打开,输入命令!analyze -v进行自动分析,也可结合上面介绍的命令进行分析。
    在这里插入图片描述
    .ecxr;kbn
    查看崩溃的堆栈
    .frame 0
    切到第0帧
    dv
    查看当前帧的变量信息

  • 相关阅读:
    MySQL的下载、安装、配置
    【毕业设计】深度学习+python+opencv实现动物识别 - 图像识别
    如何从 SD 卡恢复已删除文件?值得尝试的 10 款 SD 卡恢复软件解决方案
    序列化工具Protobuf在Idea中的配置和在java中的使用实例
    电流继电器JDL-1002A
    v-if与v-show
    编写一个程序,输入一个字符串,统计其中各个不同字符的出现次数。
    【洛谷 P3853】[TJOI2007] 路标设置 题解(二分答案+递归)
    【模型提分tricks】Adversarial Weight Perturbation(AWP)对抗训练
    基于Algolia实现网站全文搜索
  • 原文地址:https://blog.csdn.net/weixin_40355471/article/details/127656070