用Windbg替换老版本Qt的Cdb

用Windbg替换老版本Qt的Cdb

Qt 5.9.2的调试器有一个很讨厌的问题:单步步入、单步步过有时候会假死。此时被调试进程处于freeze状态,然而Qt Creator里面不能 resume,中断和暂停按钮也都不能用,最后只能退出整个IDE。 当然此时被调试进程也会挂掉,然后Qt Creator弹出一个窗口:

CDB报错

cdb.exe卡死的帖子很多,但指定了5.9.2版本的却很少。解决方案五花八门,有换cdb.exe的,还有换环境的。为避免其他问题,我不想折腾环境和默认的cdb。既然cdb.exe不好用,不如直接用微软钦点的调试器Windbg

下载Windbg Preview

不能用MS Store的地方参考这个issue。注意WindbgProduct Id可能变化。

调试Debug版本

写一个经典的Longest increasing subsequence:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include "mainwindow.h"

#include <QApplication>
#include <QVector>
#include <QDebug>
#include <algorithm>

int LIS(const QVector<int>& data){
    auto len = data.size();
    if(len == 0) return 0;

    QVector<int> dp(len, INT_MAX);
    for(int i = 0; i < len; i++){
        auto iter = std::lower_bound(dp.begin(), dp.end(), data[i]);
        *iter = data[i];
    }
    return std::lower_bound(dp.begin(), dp.end(), INT_MAX - 1) - dp.begin();
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QVector<int>test{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15};
    qDebug() << LIS(test);
    MainWindow w;
    w.show();
    return a.exec();
}

Windbg载入,Ctrl+Gmain,调出源码窗口,然后下断点运行:

没有natvis时的调试效果

可以看到源码断点、局部变量显示的功能都可以用了。但局部变量显示不太友好,把一个类的原始结构显示了出来。我们希望Windbg能像Visual Studio显示std::vectorstd::map那样,把内部结构转换成数组、键值对等更方便的形式。

这样的功能需要借助natvis实现,.natvis文件告诉调试器应该如何显示某种类型的变量。

配置natvis

Qt5.x版本的.natvis文件可以参考这个Repo

.nvload path加载.natvis后,变量已能正常显示:

载入natvis后的调试效果

调试Release版本

qmake中加入

1
2
QMAKE_CXXFLAGS += /Zi
QMAKE_LFLAGS += /DEBUG

即可生成.pdb文件。毕竟是release build,调试效果凑合用。