注册专用于std :: unordered_map的gdb pretty-printer [英] Registering a gdb pretty-printer for a specialization of std::unordered_map

查看:188
本文介绍了注册专用于std :: unordered_map的gdb pretty-printer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为 std :: unordered_map 的特定专业注册漂亮打印机,但由于某些原因,它始终对 std :: unordered_map使用标准的漂亮打印机而不是我的专用版本.

I'm trying to register a pretty-printer for a specific specialization of std::unordered_map, but for some reason it always uses the standard pretty-printer for std::unordered_map in gdb instead of my specialized version.

考虑以下课程

namespace ns {

class MyClass {
public:
    std::string name;
    int value = 0;
};

}  // namespace ns

我为它定义了一个gdb漂亮打印机

I have a gdb pretty-printer defined for it as

# myprinters.py -> sourced in gdb
class MyClassPrinter:
    def __init__(self, val):
        self.name = val["name"]
        self.val = val["value"]

    def to_string(self):
        return f"MyClass(name={self.name}, value={self.val})"


import gdb.printing
pp = gdb.printing.RegexpCollectionPrettyPrinter('myprinters')
pp.add_printer('MyClass', 'MyClass', MyClassPrinter)

gdb.printing.register_pretty_printer(gdb.current_objfile(), pp, replace=True)

现在考虑下面的主要功能

Now consider the main function below

int main(int argc, char *argv[]) {
    std::tuple<int, MyClass> mytuple{10, {"name10", 10}};
    std::unordered_map<int, MyClass> mymap;
    mymap.insert({10, {"name10", 10}});
    mymap.insert({15, {"name15", 15}});
    mymap.insert({25, {"name25", 25}});

    auto myobj = MyClass{"name5", 5};

    std::unordered_map<int, MyClass *> mymap2;
    mymap2.insert({10, new MyClass{"name10", 10}});  // don't worry about the new
    mymap2.insert({15, new MyClass{"name15", 15}});
    mymap2.insert({25, new MyClass{"name25", 25}});

    std::cout << "The end" << std::endl;
    return 0;
}

如果在 cout 行中添加断点并打印 myobj ,我将得到 $ 7 = MyClass(name ="name5",value = 5)符合预期.打印 mytuple mymap 也是可行的,因为gdb在STL中为容器提供了漂亮的打印机.我们得到类似

If a add a breakpoint in the cout line and print myobjI get $7 = MyClass(name="name5", value=5) as expected. Printing mytuple and mymap also works, since gdb has pretty-printers for the containers in STL. We get something like

$8 = std::tuple containing = {
  [1] = 10,
  [2] = MyClass(name="name10", value=10)
}
$9 = std::unordered_map with 3 elements = {
  [25] = MyClass(name="name25", value=25),
  [15] = MyClass(name="name15", value=15),
  [10] = MyClass(name="name10", value=10)
}

但是,我实际拥有的是带有 MyClass * 而不是 MyClass 的容器,例如 mymap2 变量.打印结果

However, what I actually have are containers with MyClass* and not MyClass, such as the mymap2 variable. Printing that results in

$10 = std::unordered_map with 3 elements = {
  [25] = 0x555555576760,
  [15] = 0x555555576710,
  [10] = 0x555555576650
}

这不是很有用.

对于我的特殊需要,我只需要名称" mymap2 中指向的每个 MyClass 对象的字段.然后,我为 std :: unordered_map< int,MyClass *> 创建了一个漂亮的打印机,但是我无法正确注册它(也许只是 std :: unordered_map的版本处于优先地位,但我无法正确禁用该假设,当尝试按

For my particular needs, I only need the "name" field of each MyClass object pointed in mymap2. Then I created a pretty-printer for std::unordered_map<int, MyClass *>, but I'm not able to register it correctly (maybe the version for just std::unordered_map is taking precedence, but I could not correctly disable to test this hypothesis. I get an error when I try to disable the pretty-printer as suggested in this question).

我尝试过

class MyUnorderedMapOfMyClassPrinter:
    def __init__(self, val):
        self.val = val

    def to_string(self):
        return "MyUnorderedMapOfMyClassPrinter"

,然后将以下行添加到定义我的漂亮打印机的python脚本中

and then added the line below to the python script defining my pretty-printers

pp.add_printer('MyUnorderedMapOfMyClassPrinter', 'std::unordered_map<int, ns::MyClass\*>', MyUnorderedMapOfMyClassPrinter)

包括新的漂亮打印机.

但是打印unordered_map不会使用我的漂亮打印机.它仍然使用来自gdb的常规 std :: unordered_map 漂亮打印机.

But printing the unordered_map does not use my pretty-printer. It still uses the regular std::unordered_map pretty-printer from gdb.

如果我确实创建了一个新类型,例如

If I do create a new type like

class MyUnorderedMap : public std::unordered_map<int, MyClass *> {};

并为 MyUnorderedMap 注册一个漂亮的打印机,然后它就可以工作了.但是我不想创建另一个类型只是为了注册漂亮的打印机.

and register a pretty-printer for MyUnorderedMap then it works. But I don't want to create another type just to be able to register a pretty-printer.

如何为 std :: unordered_map 的特定专业注册漂亮打印机?

How can I register a pretty-printer for a specific specialization of std::unordered_map?

修改:我不能仅禁用 std :: unordered_map 漂亮打印机,但是我在gdb中使用 disable pretty-printer 禁用了所有漂亮打印机,然后仅通过 enable pretty-printer global myprinters 启用了我的漂亮打印机.这使我可以尝试使用正则表达式来注册我的漂亮打印机并使其与 pp.add_printer('MyUnorderedMapOfMyClassPrinter','std :: unordered_map<.*,ns :: MyClass\ *>',MyUnorderedMapOfMyClassPrinter)(请注意最后的"*",因为我只希望它适用于 MyClass 指针).

I could not disable only the std::unordered_map pretty-printer, but I disabled all pretty-printers with disable pretty-printer in gdb, and then enabled only my pretty-printers with enable pretty-printer global myprinters. This allowed me try the regexp to register my pretty-printer and to make it work for a std::unordered_map specialization with with pp.add_printer('MyUnorderedMapOfMyClassPrinter', 'std::unordered_map<.*, ns::MyClass\*>', MyUnorderedMapOfMyClassPrinter) (note the "*" at the end, since I only want it to work for MyClass pointers).

有趣的是, pp.add_printer('MyUnorderedMapOfMyClassPrinter','std :: unordered_map< int,ns :: MyClass \ *>',MyUnorderedMapOfMyClassPrinter)没有工作.我出于某种原因不得不使用.* 而不是 int .

Interesting, pp.add_printer('MyUnorderedMapOfMyClassPrinter', 'std::unordered_map<int, ns::MyClass\*>', MyUnorderedMapOfMyClassPrinter) did not work. I had to use .* instead of intto make it work for some reason.

但是,当所有漂亮打印机都启用后,标准的 std :: unordered_map 漂亮打印机仍然优先于我的专业化.如何使我的漂亮打印机优先?

However, when all pretty-printers are enabled the standard std::unordered_map pretty printer still takes precedence over my specialization. How can I make my pretty-printer takes precedence?

为使内容易于再现,这是完整的 main.cpp 文件

For making things easily reproducible, here is the full main.cpp file

#include <iostream>
#include <string>
#include <tuple>
#include <unordered_map>

namespace ns {

class MyClass {
public:
    std::string name;
    int value = 0;
};

}  // namespace ns

using namespace ns;

int main(int argc, char *argv[]) {
    std::tuple<int, MyClass> mytuple{10, {"name10", 10}};
    std::unordered_map<int, MyClass> mymap;
    mymap.insert({10, {"name10", 10}});
    mymap.insert({15, {"name15", 15}});
    mymap.insert({25, {"name25", 25}});

    auto myobj = MyClass{"name5", 5};

    std::unordered_map<int, MyClass *> mymap2;
    mymap2.insert({10, new MyClass{"name10", 10}});
    mymap2.insert({15, new MyClass{"name15", 15}});
    mymap2.insert({25, new MyClass{"name25", 25}});

    std::cout << "The end" << std::endl;

    return 0;
}

和定义漂亮打印机的完整 myprinters.py 文件

and the full myprinters.py file defining the pretty-printers

class MyClassPrinter:
    def __init__(self, val):
        self.name = str(val["name"])
        self.val = val["value"]

    def to_string(self):
        return f"MyClass(name={self.name}, value={self.val})"


class MyClassPointerPrinter:
    def __init__(self, val):
        self.ptr = val
        self.name = str(val.dereference()["name"])
        self.val = val.dereference()["value"]

    def to_string(self):
        return f"Pointer to MyClass(name={self.name}, value={self.val})"



class MyUnorderedMapOfMyClassPrinter:
    def __init__(self, val):
        self.val = val

    def to_string(self):
        return "MyUnorderedMapOfMyClassPrinter"


import gdb.printing
pp = gdb.printing.RegexpCollectionPrettyPrinter('myprinters')
pp.add_printer('MyClass', '^ns::MyClass$', MyClassPrinter)
# pp.add_printer('MyClass', 'MyClass\*', MyClassPointerPrinter)
# pp.add_printer('MyClass', 'MyClass.?\*', MyClassPointerPrinter)
# pp.add_printer('MyClass', 'MyClass \*', MyClassPointerPrinter)
pp.add_printer('MyUnorderedMapOfMyClassPrinter', 'std::unordered_map<.*, ns::MyClass\*>', MyUnorderedMapOfMyClassPrinter)


gdb.printing.register_pretty_printer(gdb.current_objfile(), pp, replace=True)



def my_pp_func(val):
    if str(val.type) == "ns::MyClass *":
        return MyClassPointerPrinter(val)

gdb.pretty_printers.append(my_pp_func)

推荐答案

对我来说,问题是 gdb.current_objfile()始终返回 None .因此,您的漂亮打印机被注册为全局打印机,而所有标准打印机都是对象级别的.对象级漂亮打印机优先.

For me, the problem is that gdb.current_objfile() always returns None. Thus your pretty printer is registered as a global one, whereas all the standard ones are object level. Object level pretty-printers take precedence.

我不知道为什么,但是我无法使此功能正常工作.

I have no idea why, but I was unable to make this function work.

可以使用以下解决方法:

It is possible to use this workaround:

gdb.printing.register_pretty_printer(gdb.objfiles()[0], pp, replace=True)

这篇关于注册专用于std :: unordered_map的gdb pretty-printer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆