【问题标题】:How to iterate the elements in `std::unordered_set` with gdb's Python API?如何使用 gdb 的 Python API 迭代 `std::unordered_set` 中的元素?
【发布时间】:2021-07-09 01:11:33
【问题描述】:

我有一个具有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 返回“名称”字段的值,而不是原始指针。但是,我似乎找不到正确的方法来迭代 unordered_set 的存储桶并检索存储桶中的各个节点。在this link 中,有一个旧版本的实现给了我一些提示,但我无法正确理解。

【问题讨论】:

  • 你试过为SomeClass*创建一个漂亮的打印机吗?
  • 我有SomeClass 的漂亮打印机,但是虽然你可以为类型创建漂亮的打印机,但我不确定你是否可以为指针注册一个。我记得我过去曾尝试过此操作,但无法使其正常工作。如果有人这样做,我会再次尝试这种方法。
  • 我以前也成功过。

标签: gdb pretty-print


【解决方案1】:

事实证明,我们可以简单地为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 也会被使用而不是我们的新实现。 (见related question)。一种解决方法是定义一个继承自std::unordered_set<SomeClass*> 的新类型,例如

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

然后为MyUnorderedSetOfMyClassPointers注册漂亮的打印机。这可行,但不是最理想的,因为我们不必要地创建一个新类型来帮助调试。

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

【讨论】:

    猜你喜欢
    • 2018-09-14
    • 2020-11-23
    • 1970-01-01
    • 2012-04-13
    • 2010-11-14
    • 2019-09-23
    • 2017-11-27
    相关资源
    最近更新 更多