直接使用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