如何使用 gdb 的 Python API 迭代 'std::unordered_set' 中的元素?



我有一个类,它有一个类型为std::unordered_set<SomeClass*>的成员。 gdb 为标准库中的类型提供了漂亮的打印机,包括std::unordered_set.打印包含 7 个元素的集合会返回类似

$50 = std::unordered_set with 7 elements = {
[0] = 0x7fffffffb750,
[1] = 0x7fffffffb330,
[2] = 0x7fffffffaf10,
[3] = 0x7fffffffaaf0,
[4] = 0x7fffffffa6d0,
[5] = 0x7fffffffa2b0,
[6] = 0x7fffffffc490
}

我需要的是 gdb python 的 API 中的一种方法来自己重新实现这个漂亮的打印机,以便在迭代时我可以从SomeClass返回"name"字段的值,而不是原始指针。但是,我似乎找不到正确的方法来迭代unordered_set的存储桶并检索存储桶中的各个节点。在此链接中,有一个旧版本的实现给了我一些提示,但我无法正确处理。

事实证明,我们可以简单地导入漂亮的打印机进行std::unordered_set,并使用我们的自定义打印实现派生类。

一种可能性是

from libstdcxx.v6.printers import Tr1UnorderedSetPrinter

class UnorderedSetOfPointersPrinter(Tr1UnorderedSetPrinter):
def __init__(self, val):
Tr1UnorderedSetPrinter.__init__(self, str(val.type), val)
self._children = Tr1UnorderedSetPrinter.children(self)
self._index = 0
def children (self):
for idx, valor in self._children:
yield (idx, f'{valor.dereference()["name"]} ({valor})')
return

问题是为我们的专业化注册这台漂亮的打印机std::unordered_set.即使我们注册了这个漂亮的打印机,也会使用std::unordered_set常规的打印机而不是我们的新实现。(见相关问题)。一种解决方法是定义一个继承自std::unordered_set<SomeClass*>的新类型,例如

class MyUnorderedSetOfMyClassPointers : public std::unordered_set<SomeClass*> {};

然后注册漂亮的打印机进行MyUnorderedSetOfMyClassPointers.这有效,但它不是最佳的,因为我们不必要地创建一个新类型只是为了帮助调试。

最后,为SomeClass*实现漂亮的打印机是解决在std::unordered_set打印中只看到指针地址的原始问题的最简单解决方案,但是如果您想/需要创建自定义命令来迭代std::unordered_set元素,知道如何自定义 gdb 中已有的漂亮打印机仍然很有用, 例如。

最新更新