# gdb查看unordered_map等stl容器内容

# 现象
在默认gdb操作下，查看unordered_map时，输出信息中只包含了很多STL库内部数据结构，但无法直观查看其中的节点数据。如下所示：

```
p m_trace_map
$1 = {
  _M_h = {
    <std::__detail::_Hashtable_base<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, msrpi::TraceFlowInfo_T<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >, std::__detail::_Select1st, std::equal_to<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Hashtable_traits<true, false, true> >> = {
      <std::__detail::_Hash_code_base<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, msrpi::TraceFlowInfo_T<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >, std::__detail::_Select1st, std::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, true>> = {
        <std::__detail::_Hashtable_ebo_helper<0, std::__detail::_Select1st, true>> = {
          <std::__detail::_Select1st> = {<No data fields>}, <No data fields>},
        <std::__detail::_Hashtable_ebo_helper<1, std::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, true>> = {
          <std::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >> = {
            <std::__hash_base<unsigned long, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >> = {<No data fields>}, <No data fields>}, <No data fields>},
        <std::__detail::_Hashtable_ebo_helper<2, std::__detail::_Mod_range_hashing, true>> = {
          <std::__detail::_Mod_range_hashing> = {<No data fields>}, <No data fields>}, <No data fields>},
      <std::__detail::_Hashtable_ebo_helper<0, std::equal_to<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, true>> = {
        <std::equal_to<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >> = {
          <std::binary_function<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool>> = {<No data fields>}, <No data fields>}, <No data fields>}, <No data fields>},
    <std::__detail::_Map_base<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, msrpi::TraceFlowInfo_T<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, msrpi::TraceFlowInfo_T<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > >, std::__detail::_Select1st, std::equal_to<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>, true>> = {<No data fields>},
    <std::__detail::_Insert<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, msrpi::TraceFlowInfo_T<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, msrpi::TraceFlowInfo_T<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > >, std::__detail::_Select1st, std::equal_to<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>, false>> = {
      <std::__detail::_Insert_base<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, msrpi::TraceFlowInfo_T<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, msrpi::TraceFlowInfo_T<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > >, std::__detail::_Select1st, std::equal_to<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >> = {<No data fields>}, <No data fields>},
    <std::__detail::_Rehash_base<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, msrpi::TraceFlowInfo_T<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, msrpi::TraceFlowInfo_T<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > >, std::__detail::_Select1st, std::equal_to<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>, std::integral_constant<bool, true> >> = {<No data fields>},
    <std::__detail::_Equality<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, msrpi::TraceFlowInfo_T<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, msrpi::TraceFlowInfo_T<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > >, std::__detail::_Select1st, std::equal_to<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>, true>> = {<No data fields>},
    <std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, msrpi::TraceFlowInfo_T<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >, true> > >> = {
      <std::__detail::_Hashtable_ebo_helper<0, std::allocator<std::__detail::_Hash_node<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, msrpi::TraceFlowInfo_T<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >, true> >, true>> = {
        <std::allocator<std::__detail::_Hash_node<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, msrpi::TraceFlowInfo_T<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >, true> >> = {
          <__gnu_cxx::new_allocator<std::__detail::_Hash_node<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, msrpi::TraceFlowInfo_T<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >, true> >> = {<No data fields>}, <No data fields--Type <RET> for more, q to quit, c to continue without paging--
>}, <No data fields>}, <No data fields>},
    members of std::_Hashtable<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, msrpi::TraceFlowInfo_T<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, msrpi::TraceFlowInfo_T<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > >, std::__detail::_Select1st, std::equal_to<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >:
    _M_buckets = 0x2ba0f9891e50,
    _M_bucket_count = 62233,
    _M_before_begin = {
      _M_nxt = 0x2ba0a81e2560
    },
    _M_element_count = 25000,
    _M_rehash_policy = {
      static _S_growth_factor = 2,
      _M_max_load_factor = 1,
      _M_next_resize = 62233
    },
    _M_single_bucket = 0x0
  }
}
(gdb)
``` 

# 修改
- 执行如下命令查看`libstdcxx`路径
```
find / -name "libstdcxx*" 2>/dev/null
```

- 结果类似如下。需注意，该美化必须具有`gcc7.3.0`及以上版本的支持，如果gcc版本过低，需要先进行升级
```
/usr/share/gcc-4.8/python/libstdcxx
/usr/local/share/gcc-7.3.0/python/libstdcxx
```

- 在**用户根路径**下新建`.gdbinit`文件
```
pekphisprb09546:~ # vi .gdbinit
```

- 在`.gdbinit`文件中输入如下内容并保存（只需修改`sys.path.insert`中的路径信息）
```shell
python
import sys
sys.path.insert(0, '/usr/local/share/gcc-7.3.0/python/libstdcxx')
from v6.printers import register_libstdcxx_printers
register_libstdcxx_printers (None)
end
```

# 效果
重新运行gdb后，查看到的效果如下。需注意使用`set print pretty on`命令打开美化开关
```
(gdb) f 3
#3  0x00000000005562dc in msrpi::Statistic::print_svc_trace_flow (this=0x134bed80, flowinfo=..., is_start=false) at stat/Statistic.cpp:173
173                 if (m_trace_map.size() > 50000)
(gdb) set print pretty on
(gdb) p m_trace_map
$1 = std::unordered_map with 25000 elements = {
  ["C13212172021236352159536342613900150065-MO"] = {
    errorCode = 0,
    flowFlag = 0,
    appSeq = 1046,
    id = "C13212172021236352159536342613900150065-MO",
    caller = "sip:+8613900150065@rcs.ims.mnc000.mcc460.3gppnetwork.org",
    callee = "sip:+8613900151065@rcs.ims.mnc000.mcc460.3gppnetwork.org",
    flowErrorDesc = "",
    flowDescs = std::vector of length 6, capacity 8 = {"GetSession:1595363462", "TCP-CONNECT:1595363462", "OnNotify<Connected>:1595363462", "W-XSTORE-OK:1595363462",
      "OnNotify<TransferSuccess>:1595363462", "OnNotify<ConnectClose>:1595363462"},
    lastTime = 1595363462
  },
  ["C13212071471236352159536342513900150011-MO"] = {
    errorCode = 0,
    flowFlag = 0,
    appSeq = 1275,
    id = "C13212071471236352159536342513900150011-MO",
    caller = "sip:+8613900150011@rcs.ims.mnc000.mcc460.3gppnetwork.org",
    callee = "sip:+8613900151011@rcs.ims.mnc000.mcc460.3gppnetwork.org",
    flowErrorDesc = "",
    flowDescs = std::vector of length 6, capacity 8 = {"GetSession:1595363461", "TCP-CONNECT:1595363461", "OnNotify<Connected>:1595363461", "W-XSTORE-OK:1595363461",
      "OnNotify<TransferSuccess>:1595363461", "OnNotify<ConnectClose>:1595363461"},
    lastTime = 1595363461
  },
......
```
