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

在编译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";
}

打包发布后,使用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

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

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


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)


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

0:000> dv /t
int * pnum = 0x00000000`00000000

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

~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
查看当前帧的变量信息

猜你喜欢

转载自blog.csdn.net/weixin_40355471/article/details/127656070