用 Visual Studio 调试 Qt 程序时的变量可视化研究


目录

运行环境

IDE:Microsoft Visual Studio Community 2019, 16.11.15

Qt:5.12.5_msvc2017, 32bit

OS:Windows 10 家庭版,21H2

背景说明

我们在使用 VS 开发 Qt 程序时,经常会遇到无法观察 Qt 类型变量值的问题。网上有类似的解决 QString 等对象的方法,如VS调试状态下查看QString等QT变量_阿莫西林夹馍的博客-CSDN博客,不过像 QMainWindowQWidget 等对象监控起来还是有些不方便,网上也没有搜到解决方法。调试Qt自带例子 addressbook ,在main.cpp 里查看 mw 变量,看到的主要就是一系列地址,用处不大。如果调试时想看下窗口的 caption 怎么办?

image

Qt 类的封装

  1. QObjectQWidgetQMainWindow 的继承关系如下图所示。它们内部都有一个对应的“Private类”,指向内部的参数,即:QObjectPrivateQWidgetPrivateQMainWindowPrivate,而且Private类都是在cpp文件中定义的,因此它们的定义其实被“隐藏”了,外部是不可见的。

    image

  2. 深入QObject可以知道Private类对象对应的是d_ptr,一个智能指针对象。

    image

  3. QMainWindow 是怎么访问 d_ptr 的?用 Q_D 宏。

    image

  4. Q_D 宏的定义,先调用d_func(),再调用qGetPtrHelper()获取d_ptr指向的对象,并已经完成类型转换,QMainWindow直接获得QMainWindowPrivate对象。

    image

  5. 看到一个 有意思的地方,用 operator->() 访问智能指针内部保存的裸指针。下面我们就试试这个运算符。

    image

用VS监视对象

  1. VS变量监视器直接访问d_ptr,得到的是QScopedPointer对象,不是我们要的;

    image

  2. 加上运算符,VS识别到了实际的类型,太棒了!

    image

    找到 caption 了,记住这串代码,后面有用。注意:类型里还有动态库名称的限制。

    (*((Qt5Widgetsd.dll!QWidgetPrivate*)&(*((Qt5Widgetsd.dll!QMainWindowPrivate*)this->d_ptr.operator->())))).extra->topextra->caption
    

    image

使用 natvis 文件

Natvis文件已经替换autoexp.dat文件来自定义监视变量,可以在项目中添加natvis文件,也可以更改用户级别的natvis文件。

  1. 在项目中使用natvis文件

    • 添加natvis文件

      image

    • 编辑natvis文件

      <?xml version="1.0" encoding="utf-8"?> 
      <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
      
        <Type Name="QMainWindow">
          <DisplayString>{{ caption = {(*((Qt5Widgetsd.dll!QWidgetPrivate*)&amp;(*((Qt5Widgetsd.dll!QMainWindowPrivate*)this-&gt;d_ptr.operator-&gt;())))).extra-&gt;topextra-&gt;caption} }}</DisplayString>
        </Type>
      
      </AutoVisualizer>
      

      因为natvis文件是xml格式的,所以“>”、“<”、“&”等要用实体引用

  2. 使用用户级别natvis

    • 直接编辑C:/Users/[user name]/Documents/Visual Studio 2019/Visualizers下的natvis文件

      image

效果

可以显示 caption 信息了! 其他更多功能,就自由发挥啦。image

image

参考文献

原创文章,作者:Carrie001128,如若转载,请注明出处:https://blog.ytso.com/277956.html

(0)
上一篇 2022年7月31日
下一篇 2022年7月31日

相关推荐

发表回复

登录后才能评论