Boost 无序映射的美化打印函数多次打印值及不必要的值

1 投票
1 回答
654 浏览
提问于 2025-04-17 23:08

我正在尝试为boost::unordered_map添加一个漂亮的打印功能,也就是想在现有的boost漂亮打印器列表中增加一个新的打印器。你可以在这里找到相关信息:https://sourceware.org/gdb/wiki/STLSupporthttps://github.com/ruediger/Boost-Pretty-Printer

但是,当我尝试打印我的map时,很多值被打印了多次,还有一些不想要的字符。我不太确定我的代码还需要做什么修改,才能让它只打印一次值,并且没有任何多余的字符。这里是我在myMap.cpp中更新myMap的循环:

 for (int i=0; i<=10; i++)
 {
 string s = to_string(i);
 myMap[s] = i;
 }

然后当我在gdb中打印myMap时,代码是:

(gdb)p myMap 

我得到的结果如下:

$1 = boost::unordered::detail = {"1" = 1, "0" = 0, "2" = 2, "1" = 1, "0" = 0, "3" = 3, 
"2" = 2, "1" = 1, "0" = 0, "4" = 4, "3" = 3, "2" = 2, "1" = 1, "0" = 0, "5" = 5, "4" = 4, 
"3" = 3, "2" = 2, "1" = 1, "0" = 0, "6" = 6, "5" = 5, "4" = 4, "3" = 3, "2" = 2, "1" = 1, 
 "0" = 0, "7" = 7, "10" = 10, "6" = 6, "5" = 5, "4" = 4, "3" = 3, "2" = 2, "1" = 1, 
"0" = 0, "8" = 8, "7" = 7, "10" = 10, "6" = 6, "5" = 5, "4" = 4, "3" = 3, "2" = 2, 
"1" = 1, "0" = 0, "9" = 9, "8" = 8, "7" = 7, "10" = 10, "6" = 6, "5" = 5, "4" = 4, 
"3" = 3, "2" = 2, "1" = 1, "0" = 0, 
" \204`", '\000' <repeats 13 times>, "\321\n\002", '\000' <repeats 181 times>... = 0, 
"9" = 9, "8" = 8, "7" = 7, "10" = 10, "6" = 6, "5" = 5, "4" = 4, "3" = 3, "2" = 2, 
"1" = 1, "0" = 0}

我的漂亮打印器的python代码看起来是这样的:

@_register_printer
class BoostUnorderedMap:
"Pretty Printer for boost::unordered_map"
printer_name = 'boost::unordered_map'
version = '1.40'
type_name_re = '^boost::unordered::unordered_map<.*>$'

class _iterator:
def __init__(self,fields):
   type_1 = fields.val.type.template_argument(0)
   type_2 = fields.val.type.template_argument(1)

   self.buckets = fields.val['table_']['buckets_']
   self.bucket_count = fields.val['table_']['bucket_count_']
   self.bucket_size = fields.val['table_']['size_']
   self.current_bucket = 0
   self.value = 0
   self.iteration = 0
   self.temp_node = 0
   self.bucket_to_start = 0
   pair = "std::pair<%s const, %s>" % (type_1, type_2)
   self.pair_pointer = gdb.lookup_type(pair).pointer()
   self.base_pointer = gdb.lookup_type("boost::unordered::detail::value_base< %s >" % pair).pointer()
   self.node_pointer = gdb.lookup_type("boost::unordered::detail::ptr_node<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> >").pointer()
   self.node = self.buckets[self.current_bucket]['next_']



def __iter__(self):
    return self

def next(self): 
    while not self.node:
            self.current_bucket = self.current_bucket + 1
            if self.current_bucket >= self.bucket_count:
                raise StopIteration
            self.node = self.buckets[self.current_bucket]['next_']

    iterator = self.node.cast(self.node_pointer).cast(self.base_pointer).cast(self.pair_pointer).dereference()   
        self.node = self.node['next_']

        return ('%s' % iterator['first'], iterator['second'])

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

def children(self):
return self._iterator(self)

def to_string(self):
return "boost::unordered::detail"

任何帮助都会非常感谢。

1 个回答

0

要确切知道哪里出问题了,其实需要对Boost的内部工作原理有更多了解。如果是我,我可能会在“next”方法里加一些调试打印,看看到底哪里出了岔子。

不过,有一件事在你的Python代码中很明显。现在你是这样返回子元素的:

    return ('%s' % iterator['first'], iterator['second'])

但是,通常使用这个API的方式是把映射的键和值作为不同的子元素返回,然后再有一个叫做display_hint的方法返回“map”。具体可以参考:

https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing-API.html

你可以很简单地在“next”方法里用“yield”来实现这个功能。

撰写回答