`
tomhibolu
  • 浏览: 1382595 次
文章分类
社区版块
存档分类
最新评论

Qt Creater、Gdb之Pretty Printer小记

 
阅读更多
  • 有相当长一段时间,没搞清 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
    • 易用、易扩展。但有些场合尚无法使用...

参考


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics