【问题标题】:Debugging gdb pretty printers调试 gdb 漂亮的打印机
【发布时间】:2015-11-20 23:20:39
【问题描述】:

我已经开始尝试为我的一些 C++ 数据结构构建 gdb 漂亮的打印机,但是 documentation 非常薄。

因此,我需要猜测如何做事,而且我漂亮的打印机经常会因无用的 python 异常而崩溃,而没有指示实际问题出在哪里。

有什么好的方法可以调试漂亮的打印机吗?通过在代码中插入对 pydb 的显式调用,我在其他 python 程序中取得了成功:

import pydb
pydb.debugger()

但在 gdb 中运行 python 时这似乎不起作用——它只是运行通过 debugger 调用并且不会停止或说或做任何事情。

【问题讨论】:

  • 确保您set python print-stack full。这将使您从异常中获得完整的堆栈跟踪。我从来没有为我的漂亮打印机尝试过 python 调试器。我主要是做打印调试。

标签: python debugging gdb pretty-print


【解决方案1】:

您可以在 gdb 中运行 pdb(python 调试器之一)。下面是一个 gdb 会话的摘录,带有一个简单的示例:

(gdb) print (ObjectSignature *) 0x7f71e4018000
$1 = (ObjectSignature *) 0x7f71e4018000
(gdb) python import pdb
(gdb) python pdb.run('gdb.execute("print $1[0]")')
> <string>(1)<module>()
(Pdb) from svtprinters.printers import ObjectSignaturePrinter
(Pdb) b ObjectSignaturePrinter.to_string
Breakpoint 1 at /svtfs/svtprinters/printers.py:195
(Pdb) c
$2 = > /svtfs/svtprinters/printers.py(196)to_string()
-> sizetypestr = 'invalid'
(Pdb) n
> /svtfs/svtprinters/printers.py(197)to_string()
-> sizetypeidx = int(self.val['mSizeType'])
(Pdb) self.val['mSizeType']
<gdb.Value object at 0x7effc90ff430>
(Pdb) int(self.val['mSizeType'])
3
(Pdb) n
> /svtfs/svtprinters/printers.py(199)to_string()
-> if sizetypeidx < len(self.sizetypes):
(Pdb) self.sizetypes
['unknown', 'meta_1K', 'data_4K', 'data_8K', 'data_16K', 'data_32K', 'data_64K']
(Pdb) n
> /svtfs/svtprinters/printers.py(200)to_string()
-> sizetypestr = self.sizetypes[sizetypeidx]
(Pdb) 
> /svtfs/svtprinters/printers.py(202)to_string()
-> return (20*"%02x"+" %s") % tuple([self.val['mValue'][i] for i in range(20)]+[sizetypestr])
(Pdb) sizetypestr
'data_8K'
(Pdb) c
98d6687a2ea63a134901f0df140b13112e64bfb7 data_8K
(gdb) 

在这个例子中,ObjectSignaturePrinter 是一个类,它通过gdb.pretty_printers$1 中的ObjectSignature 类型相关联。第二个print 命令的输出被拆分; $2 = 在到达漂亮的打印机断点之前打印,其余的输出出现在pdb continue 命令之后。

这种方法的变体很可能适用于其他 python 调试器。

【讨论】:

  • 当我尝试这个时,我可以到达(Pdb) 提示符,但是当我尝试使用b MyObjectPrinter.to_string 设置断点时,它只会给我消息End of file。继续给我同样的 gdb.error 没有机会找出问题所在。试图一步只是把我埋在 gdb 的 python 代码中
  • 我编辑了我的答案以使用导入语句和更简单的断点命令。如果我省略该 import 语句并使用更简单的断点命令,我会得到以下输出:*** The specified object 'ObjectSignaturePrinter.to_string' is not a function or was not found along sys.path.。我没有解释为什么你的断点命令会报告它报告的错误,但是尝试一下它可能会提供有用的信息。如果您只输入函数名称(省略b),那应该会告诉您pdb 是否识别该名称。
  • 我在Pdb.checkline 中找到了End of file 消息的明显来源(在我的系统上为/usr/lib/python2.7/pdb.py,用于我为此使用的gdb 二进制文件)。如果您仅指定函数名称,我不确定为什么它会找到不认为可执行的行。即使我将我的to_string 方法替换为只有一个pass 语句,或者只是一个字符串而没有别的,断点对我也有效。和以前一样,了解pdb 如何解释该函数名可能会有所帮助。对我来说,它在导入后显示为未绑定的方法(如果我在导入前尝试,我会得到 NameError)。
【解决方案2】:

出于同样的目的,我正在使用 IPython 探索 GDB API。我可以在 GDB 中启动一个 IPython 内核,然后从另一个终端中的另一个 IPython 控制台连接到它。从那里可以在运行的 GDB 进程中以交互方式使用 Python API。

我在.gdbinit 文件中为 GDB 定义了一个辅助命令:

# gdb command to start an embedded ipython kernel.
# connect to it with "ipython3 console --existing ..."
# use gdb.parse_and_eval() to evaluate variables etc.
define ipython_embed
  python
import sys
print(sys.version)
# helper functions
import gdb
def gdb_run(cmd):
  print(gdb.execute(cmd, to_string=True))
def gdb_eval(expression):
  return gdb.parse_and_eval(expression)
def gdb_vis(value):
  return gdb.default_visualizer(value)
import IPython
IPython.embed_kernel()
  end
  # gdb command prompt is basically unusable after the ipython kernel stops, so just exit gdb
  quit
end

在 GDB 中运行它会打印如下内容:

To connect another client to this kernel, use:
    --existing kernel-2701.json

在另一个终端中,使用这些命令行选项运行 ipython console 以连接到 GDB。然后,您可以轻松使用 GDB API。

要调试您的可视化工具,请使用gdb.parse_and_eval()(或gdb_eval())获取可打印的表达式,使用gdb.default_visualizer()(或gdb_vis())获取关联的打印机类,然后调用/调试您的方法。

请注意,您可能需要安装一些额外的软件包以获得必要的 IPython 支持,并且某些细节可能会因 Python 和 GDB 版本而异。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-26
    相关资源
    最近更新 更多