首页 > 其他分享 >第三方IDE使用gdb调试Qt实现pretty print

第三方IDE使用gdb调试Qt实现pretty print

时间:2023-10-13 18:25:43浏览次数:52  
标签:Qt val self py gdb ..... pretty qt

  直接使用gdb调试Qt应用时,Qt的一些数据类型没法友好的显示出来,而qtcreator可以很好的展示出来,qtcreator也是通过gdb来调试的,在展示数据时,其实是gdb通过python脚本来处理后显示的,这些python脚本位于/usr/share/qtcreator/debugger这个位置(ubuntu20.04)。

gdb在启动时,会自动在某些目录寻找初始化脚本,一般为:

 ~/etc/gdb/gdbinit
 ~/.gdbinit
 ./.gdbinit

也可以在gdb启动后,手动指定加载初始化脚本source your_gdbinit。按照/usr/share/qtcreator/debugger里面的README.txt,我在~/.gdbinit加了加载命令后,发现不能正常工作。在网络上搜索到kde项目用的kdevelop gdb printers,kde是使用Qt作为GUI开发框架的一个东西,与之对应的是gnome。
 
  首先将连接里面的3个py文件保存到~/.gdb/qt5prettyprints目录下,其中kde.py可以不用。然后将gdbinit文件保存为~/.gdbinit。需要稍微改下这个文件:

python

#新增下面两行
import sys, os
sys.path.insert(0, "/home/a/.gdb/qt5prettyprinters")

from qt import register_qt_printers
register_qt_printers (None)

#这两句看你是否需要做kde开发
from kde import register_kde_printers
register_kde_printers (None)

end

新增的两行的意思是,给第三方的模块(qt.py, kde.py, helper.py)设置搜索路径,因为这3个python文件保存在我自定义的位置。现在就可以在gdb,甚至是第三方IDE中通过gdb来直观的观察变量了。
 

具体支持哪些Qt内置类型,可以看qt.py脚本的build_dictionary函数,当前为20个。
 
  在CLion中使用这个qt pretty print的python脚本时,遇到一个bug,就是当QDateTime类型作为参数传递时,如果在这在函数上下断点会引起qt.py这个脚本执行异常,导致程序直接退出。例如下面这个例子

如果仅下2,3号断点,不进使用QDateTime作为参数的foo函数,不会有异常,但是如果下了1号断点,程序进入foo直接退出。一开始我使用CLion调试,总是莫名其妙的退出,折腾了1个小时才发现这个规律。但是不知道原因。无意中抛开CLion直接用gdb调试,才发现是python脚本出了问题,如下图:

查看下qt.py脚本里面打印QDateTime类型的处理函数:

class QDateTimePrinter:

    def __init__(self, val):
        self.val = val

    def to_string(self):
        time_t = gdb.parse_and_eval("reinterpret_cast<const QDateTime*>(%s)->toSecsSinceEpoch()" % self.val.address)
        return time.ctime(int(time_t))

  gdb.parse_and_eval很容易看得懂,就是gdb的eval命令,然后结果返回给time_t,再通过time.ctime将time_t转为字符串,返回,也就是print一个QDateTime变量时,显示的字符串。

  再分析下不用qt.py时,直接执行eval,看得到什么结果,先注释~/.gdbinit里面初始化语句,不加载qt.py。然后在foo函数下断点,执行eval。

可以看到eval执行时就报了内存访问错误了。只能改qt.py里面打印QDateTime的逻辑了。经过调试我改为下面的样子:

class QDateTimePrinter:

    def __init__(self, val):
        self.val = val

    def to_string(self):
        sec = self.val['d']['data']['msecs'] / 1000
        localsec = time.localtime(sec + time.timezone)
        return time.strftime("%Y-%m-%d %H:%M:%S", localsec)

  首先它拿到毫秒时间戳,取秒,然后根据本地时区,转为字符串格式。至于为什么self.val['d']['data']['msecs']可以拿到毫秒时间戳,可以看下class QDateTime的定义:

class QDateTime
{
    .....
    .....
  struct ShortData
  {
    .....
    .....
    quintptr status : 8;
    qintptr msecs : sizeof(void *) * 8 - 8;
  }

  union Data
  {
    .....
    .....
      QDateTimePrivate *d;
      ShortData data;
    .....
    .....
  }
  private:
  Data d;
    .....
    .....
}

标签:Qt,val,self,py,gdb,.....,pretty,qt
From: https://www.cnblogs.com/thammer/p/17762862.html

相关文章

  • QT基础教程(QPalette和QIcon)
    (文章目录)前言本篇文章继续讲解QT中的知识,主要为大家讲解QPalette和QIcon。QPalette和QIcon都是Qt框架中用于图形界面设计的类,它们分别用于管理调色板和图标的相关功能。一、QPalette类QPalette(调色板)QPalette类用于管理和控制Qt应用程序的颜色方案,它定义了各种图形界......
  • QT部件透明阴影效果和透明窗体
      透明效果1.设置整个窗体透明调用setWindowOpacity()方法,传入一个0~1之间的值来表示透明度;1表示不透明,0表示完全透明,在构造函数中添加setWindowOpacity(0.5);//0~1之间2.设置窗体透明,部件不透明在构造函数中添加//设置窗体透明this->setAttribute(Qt::WA_Transluc......
  • QT--QString的arg方法
    在QT的QString中,arg方法类似于C中的printf中使用的格式输出符(只是有点类似)。在QT5的帮助文档中,可以看出以下几点:使用arg(str1,str2,str3)这种方法进行替换。使用arg(str1).arg(str2).arg(str3)这种方法进行替换。​使用arg(int, int, int)这种方式进行替换。解释......
  • 关于vscode编写qt,qdebug无法输出到终端的问题
    这个问题主要是cmake那边的qt设置没弄好。其中WIN32_EXECUTABLEON。这个选项要设置为OFF。不然qdebug无法打印到终端中。如果本来就没有这set_target_properties的话,可以在cmake最后一行加上这个,并且将WIN32_EXECUTABLEON设置为OFF即可。set_target_properties(appl......
  • Qt信号槽与事件循环学习笔记
    事件与事件循环信号槽机制事件与事件循环在Qt中,事件(event)被封装为QEvent类/子类对象,用来表示应用内部或外部发生的各种事情。事件可以被任何QObject子类的对象接收并处理。根据事件的创建方式和调度方式,Qt中事件可分为三类,分别是:自发事件(Spontaneousevent)由窗口系统(windo......
  • Qto_SiteBaseQuantities
    Qto_SiteBaseQuantities场地基准工程量:场地所有引用的定义中通用的基准工程量。  NameTypeDescriptionGrossPerimeterQ_LENGTHUmfangUmfangderGrundstücksgrenze,gemesseninhorizontalerProjektion.GrossPerimeterPerimeterofthesiteboundary,......
  • Qt_C++读写NFC标签Ntag支持windows国产linux操作系统
    本示例使用的发卡器:ntag2标签存储结构说明#include"mainwindow.h"#include"./ui_mainwindow.h"#include<QDebug>#include"QLibrary"#include"QMessageBox"//本示例可在windows、linux系统内编译、运行//判断windows、linux系统,声明动态库函数---------------......
  • QT串口QSerialPort类循环接收可能导致的数据接收不到问题。
    QT串口QSerialPort类循环接收可能导致的数据接收不到问题。建议在使用readAll前调用bytesAvailable来判断缓存区数据是否存在。下面这个程序为错误示范,可能会导致串口数据一直无法读取。QByteArrayresponseData;if(m_serialport->isOpen()){m_serialport->waitForRead......
  • 轻量通讯协议 --- MQTT
    介绍一、MQTT简介MQTT(MessageQueuingTelemetryTransport)是一种轻量级的消息传输协议,通常用于在物联网(IoT)和传感器网络中进行通信。它设计用于在低带宽、不稳定或高延迟的网络环境下传输数据,因此非常适用于连接设备之间的通信,尤其是在资源有限的环境中。MQTT的主要特点包括......
  • 【PyQt6】Python窗口拖拽文件并响应的实现
    情景大概应用情景为:将一个文件拖入到窗口内,地址栏显示文件路径,文本框显示文件内容。说明实现拖拽必须在exec前设置QMineDate,否则不会开始拖拽操作。实现fromPyQt6.QtCoreimport*calssMainWindow(QMainWindow,Ui_MainWindow): def__init__(self): super().__init__......