- 有相当长一段时间,没搞清 Qt Creator 目录中的那堆python文件是干嘛用,以及在何处嵌入的python的解释器。
- 后来用depends查看各个可执行文件,才发现是 gdb 在需要这些文件。可还是不清楚干嘛用的...
-
再后来,终于注意到,Manual中对此不是说的很清楚么!Using Debugging Helpers。
似乎总是这样,总是一开始不够仔细。于是,踏破铁鞋无觅处,...
Pretty-Printer
Gdb 从7.0 开始增加了python脚本控制变量输出样式的特性。
先看个例子:
#include <QtCore/QtByteArray> #include <QtCore/QDebug> int main(int argc, char **argv) { QByteArray bytes("\x01\x00\x01\x02\x03", 5); qDebug()<<bytes.toHex(); }
- 使用任何熟悉的方式编译它:(比如,可以通过如下的一条命令)
g++ -g main.cpp -IE:\Qt\4.7.3\include -LE:\Qt\4.7.3\lib -lQtCore4 -o main
- 启用gdb,调试时,查看变量bytes的值:
(gdb) p bytes $1 = {static shared_null = <optimized out>, static shared_empty = <optimized out>, d = 0x3e2a30} (gdb) p bytes.d.size $2 = 5 (gdb) p bytes.d.data[0] $3 = 1 '\001'
挺让难受的,直接看bytes几乎看不到任何信息,只能通过一点点看。
- 而如果我们为QByteArray写一个Pretty-Printer ,效果就不同的:
(gdb) p bytes $1 = "size: 5 data: 01 00 01 02 03"
脚本?
准备脚本还是挺麻烦的,上面用的脚本是其实这个模样:
#qt_printer.py import gdb import re class QByteArrayPrinter(object): '''Print a QByteArray''' def __init__(self, val): self.val = val def to_string(self): size = self.val['d']['size'] data = self.val['d']['data'] res = "size: %d data: " % size for i in range(size): res += " %02X" % data[i] return res def display_hint (self): return 'string' def lookup_function (val): "Look-up and return a pretty-printer that can print val." typename = val.type.tag if typename == None: return None regex = re.compile('^QByteArray$') if regex.match(typename): return QByteArrayPrinter(val) return None def register_printers (obj): obj.pretty_printers.append (lookup_function)
- 定义了一个类QByteArrayPrinter:控制打印的结果
- 定义一个函数 lookup_function:根据要打印的变量类型来确定使用哪一个Printer
- 定义一个函数register_printers:来注册我们的上一个查找函数
.gdbinit
Gdb启动时会加载一个名为.gdbinit的文件
- 系统级的init文件,gdb自身被编译时通过 --with-system-gdbinit 指定
-
用户级init文件,在用户家目录下的 ~/.gdbinit (在windows下,通过环境变量HOME指定 fixme?)
- 工作目录下的 .gdbinit 文件
注意:在window下,在Explorer中无法创建以"."开头的文件,但在控制台下可以。
所以,我们可以直接在工作目录下放置一个:
- .gdbinit 文件
python import sys sys.path.insert(0, 'd:\\Qt\\test-mingw') from qt_print import register_printers register_printers(gdb) end set print pretty 1
所做的工作就是调用一下我们上一个脚本中的 register_printers 这个函数,由于我们脚本文件随便放置,所以需要通过sys指定其所在目录。
gdb 与 python
linux下东西基本都是现成的。
在Windows下,
- Qt Creator 安装包中提供的gdb已经启用的python支持(而且自带了、嵌入了一个 python),可以直接使用。
- MinGW 官方提供的gdb二进制包中,也提供了支持python的版本,解压后可见到类似 gdb-python27.exe 的东西,但使用的话需要你自己安装相应版本的Python。
Qt Creator
前面说了一堆,其实Qt Creator并没有使用gdb提供的这个东西。而是自己弄了一套 dumper。原因见Peek and Poke, Vol. 2一文中Andre给出的评论。在其安装目录下的 share\qtcreator\dumper 目录下可以看到相关的文件。如何扩展自己的类型,Qt Creator手册中有具体介绍。
Qt Creator 称其为 Debugging Helpers。有两套,
- 一套基于C++
- MSVC、Mac OS、老的linux发行版,只能用这个东西
- 另一套基于Python
- 易用、易扩展。但有些场合尚无法使用...
参考
-
http://sourceware.org/gdb/current/onlinedocs/gdb/Pretty_002dPrinter-Introduction.html
-
http://nikosams.blogspot.com/2009/10/gdb-qt-pretty-printers.html