微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

解决方法

事实证明,我们可以简单地为 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 打印中只看到指针地址的原始问题的最简单的解决方案,但已经知道如何自定义漂亮的打印机例如,如果您想要/需要创建自定义命令来迭代 std::unordered_set 元素,在 gdb 中仍然很有用。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。