使用GDB来进行STL容器的调试
现代C++中STL使用的越来越普遍,较之其它类型,stl容器类的调试显得复杂度更好。本篇以map为例说明如何利用gdb来遍历map中的各成员变量。
源码如下:
#include <map> #include <iostream> #include <string> using namespace std; int main(int arg, char** argv) { map<int, string> mapExample; mapExample.insert(pair<int,string>(1,"demo_one")); mapExample.insert(pair<int,string>(2,"demo_two")); mapExample.insert(pair<int,string>(3,"demo_three")); map<int,string>::iterator iter; for ( iter = mapExample.begin();iter!=mapExample.end();iter++) { cout<<iter->second<<endl; } return 0; }
编译运行:
g++ -o demo -g stl_test.cpp
运行
gdb ./demo
br 14
r
显示mapExample容器中的各个元素
p mapExample $1 = std::map with 3 elements = {[1] = "demo_one", [2] = "demo_two", [3] = "demo_three"}
如果想要知道每个element的所在的内存区域,需要先得到stl map的类型。
ptype mapExample
显示如下,成员函数部分略去。
type = class std::map<int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<int>, std::allocator<std::pair<int const, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > [with _Key = int, _Tp = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<int const, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >] { private: _Rep_type _M_t;
至此关键性成员变量显示即_M_t
顺着这条思路继续往下,查看_M_t的结构定义
p mapExample._M_t
结果显示出stl map实现使用了红黑二叉树rb-tree
_M_impl = { <std::allocator<std::_Rb_tree_node<std::pair<int const, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >> = { <__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >> = {<No data fields>}, <No data fields>}, members of std::_Rb_tree<int, std::pair<int const, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<int const, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<int>, std::allocator<std::pair<int const, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_Rb_tree_impl<std::less<int>, false>: _M_key_compare = { <std::binary_function<int, int, bool>> = {<No data fields>}, <No data fields>}, _M_header = { _M_color = std::_S_red, _M_parent = 0x6040b0, _M_left = 0x604040, _M_right = 0x604120 }, _M_node_count = 3 } }
至此,事情变的简单了,利用_M_left和_M_right就可以遍历各个二叉树结点了。
手工方式作一次不会觉着很累,但次次都手工查看会觉着不厌其烦。幸运的是,早有人已经提供了自动化的脚本。具体链接如下
https://gist.github.com/skyscribe/3978082
使用方法是将上述链接中的内容保存到~/.gdbinit中,如果没有.gdbinit就手工创建一个,该文件在gdb每次启动时会被最先读入。
有了上述脚本,就可以用plist, pmap, pvector来遍历stl容器了。