如何使 C++ 类 gdb 友好?
Posted
技术标签:
【中文标题】如何使 C++ 类 gdb 友好?【英文标题】:How to make a C++ class gdb-friendly? 【发布时间】:2020-09-16 17:06:46 【问题描述】:考虑以下示例:
std::string s = "Hello!!";
(gdb) p s
$1 = "Hello!!";
本质上,只提供变量名就足以显示字符串。例如,我不必键入“p s.c_str()”。
gdb 是否使用任何隐式运算符来获取显示字符串?我需要为我的班级做类似的事情。这是我班级的一个简单示例:
class MyClass
private:
std::string _name;
;
【问题讨论】:
您需要使用 gdb 的脚本工具来为您自己的类型添加漂亮的打印机。请参阅:***.com/questions/12574253/… 它是gdb的特性之一,实际上有pretty-printers
用来显示标准类,可以用来表示自定义。对于std::string
,旧版本的 gdb 无法做到这一点。要创建自定义漂亮打印机,可以在 gdb 命令行中使用定义命令或编写 python 漂亮打印机。像这样的简单案例可以用我的宏来完成。 kurokatta.org/grumble/2018/05/gdb-pretty
确保在构建时启用了调试符号。
【参考方案1】:
你需要为你的班级写一个漂亮的打印机。这不是您在 C++ 类中执行的操作,而是您在 gdb 中执行的操作(尽管与您的 C++ 类匹配)。最简单的方法是通过 gdb 的 Python API(您也可以使用 Guile 语言)。
GDB 已经为大多数标准库类提供了漂亮的打印机,这就是为什么您可以轻松看到 std::string
对象、std::vector
等。如果您在 gdb 中键入 info pretty-printer
,它会告诉您关于它目前知道的漂亮打印机,你会注意到很多std::something
漂亮的打印机。
如果您使用 pass /r
到 gdb 中的打印命令,它将打印变量,而不使用任何可能的注册漂亮打印机匹配它。用std::string
试试看,如果 gdb 没有为它提供漂亮的打印机,它会如何打印。
那么,您如何编写自己的漂亮打印机呢?为此,您应该阅读有关此主题的 GDB's documentation。但我发现通过阅读和调整一些现有的漂亮打印机开始更容易,然后阅读 gdb 的文档了解详细信息。
例如,我的一个项目中有一个Coordinate
类,如下所示
class Coordinate
private:
double x;
double y;
double z;
public:
...
为这个类写一个漂亮的打印机很容易。您使用以下代码创建一个 python 文件
class CoordinatePrinter:
def __init__(self, val):
# val is the python representation of you C++ variable.
# It is a "gdb.Value" object and you can query the member
# atributes of the C++ object as below. Since the result is
# another "gdb.Value" I'am converting it to a python float
self.x = float(val['x'])
self.y = float(val['y'])
self.z = float(val['z'])
# Whatever the `to_string` method returns is what will be printed in
# gdb when this pretty-printer is used
def to_string(self):
return "Coordinate(x=:.2G, y=:.2G, z=:.2G)".format(self.x, self.y, self.z)
import gdb.printing
# Create a "collection" of pretty-printers
# Note that the argument passed to "RegexpCollectionPrettyPrinter" is the name of the pretty-printer and you can choose your own
pp = gdb.printing.RegexpCollectionPrettyPrinter('cppsim')
# Register a pretty-printer for the Coordinate class. The second argument is a
# regular expression and my Coordinate class is in a namespace called `cppsim`
pp.add_printer('Coordinate', '^cppsim::Coordinate$', CoordinatePrinter)
# Register our collection into GDB
gdb.printing.register_pretty_printer(gdb.current_objfile(), pp, replace=True)
现在我们需要做的就是source
gdb 中的这个 python 文件。为此,请写入您的 .gdbinit 文件
source full_path_to_your_python_file_with_pretty_printers.py
当您启动 gdb 时,它将运行您的 .gdbinit
文件,该文件将加载您的漂亮打印机。请注意,这些漂亮的打印机通常也可以在使用 gdb 的 IDE 中工作。
如果您对更多示例感兴趣,我已经为Armadillo 库(向量、矩阵和一般线性代数)中的某些类创建了漂亮的打印机,这些类可在here 获得。
【讨论】:
【参考方案2】:如果您安装了libstdc++ pretty-printers(您已经安装了它们),那么您的类已经是 gdb 友好的,因为它们将在打印您的类的成员时被调用。如果除了_name
之外还有很多其他班级成员,您还可以使用set print pretty
更容易区分它们:
(gdb) p my_class
$1 = _name = ""
(gdb) set print pretty
(gdb) p my_class
$2 =
_name = ""
(gdb)
【讨论】:
以上是关于如何使 C++ 类 gdb 友好?的主要内容,如果未能解决你的问题,请参考以下文章