调试std::string
首先需要了解std::string的实现原理
string是STL中最为常用的类型,它是模板类basic_string用char类型特化后的结果,下面我们来看一下string类型的基本组成:
typedef basic_string<char> string; struct _Rep_base
{
size_type _M_length;
size_type _M_capacity;
_Atomic_word _M_refcount;
}; struct _Alloc_hider
{
_CharT* _M_p;
}; mutable _Alloc_hider _M_dataplus;
_M_data() const { return _M_dataplus._M_p; }
_Rep* _M_rep() const { return &((reinterpret_cast<_rep *> (_M_data()))[-1]); }
string只有一个成员_M_dataplus。但是这里需要注意的是,string类在实现的时候用了比较巧的方法,在_M_dataplus._M_p中保存了用户的数据,在_M_dataplus._M_p的第一个元素前面的位置,保存了string类本身所需要的一些信息rep。这样做的好处,一方面不增加string类的额外开销,另一方面可以保证用户在调试器(GDB)中用_M_dataplus._M_p查看数据内容的时候,不受干扰。用户可以通过reinterpret_cast<_rep *> (_M_data()))[-1])来查看rep相关的信息,也可以调用_M_rep()函数来查看。
(gdb) p &base
$3 = (const std::locale::string *) 0x7fffffffe9d0
拿到string的_Rep结构
(gdb) p *((const std::locale::string* )0x7fffffffe9d0)->_M_rep()
$9 = {
<std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Rep_base> = {
_M_length = 10485760,
_M_capacity = 10489799,
_M_refcount = 0
},
members of std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Rep:
static _S_max_size = 4611686018427387897,
static _S_terminal = 0 '\000',
static _S_empty_rep_storage = {0, 0, 0, 0}
}
如果进程已经不存在了,无法调用->_M_rep(),会报错:
(gdb) p (('google::protobuf::internal::LogMessage::string' *) 0x2e560500)->_M_rep()
You can't do that without a process to debug.
我还遇到过一种情况,在多线程环境中,调用->_M_rep()会有如下报错:
(gdb) p this->mRequest->data_->_M_rep()
[Switching to Thread 0x51931940 (LWP 10454)] Breakpoint 1, XXXX::XXXX::XXXXX::Run (this=0xa522700) at build/release64/XXXX/XXXXXX/XXXXXX/xxx.cpp:71
71 in build/release64/XXXX/XXXXXX/XXXXXX/xxx.cpp
The program stopped in another thread while making a function call from GDB. Evaluation of the expression containing the function
这是因为gdb在执行->_M_rep()函数时发生了线程切换,或者有其他线程同样执行到了break点,这种情况的一个解决方法是调整gdb的scheduler-locking策略(http://ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_39.html#SEC40):
(gdb) show scheduler-locking
Mode for locking scheduler during execution is "step".
(gdb) set scheduler-locking on
(gdb) c
Continuing.
如果没法通过->_M_rep()函数找到_Rep结构,那么只能通过下面的方法找:
1)找到_M_p结构:
(gdb) p (('google::protobuf::internal::LogMessage::string' *) 0x2e560500)->_M_dataplus
$11 = {
<std::allocator<char>> = {
<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>},
members of std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Alloc_hider:
_M_p = 0x7f9b39706018 ""
}
2)找_M_p指针前面的三个double word:
(gdb) x/32dg 0x7f9b39706018 - 32
0x7f9b39705ff8: -6052009417173884928 524288
0x7f9b39706008: 528327 4294967295
0x7f9b39706018: 0 0
上图中,524288就是_Rep的_M_length,528327就是_Rep的_M_capacity,4294967295就是_Rep的_M_refcount,这儿实际上是-1。
最新文章
- Ixia测试仪的自动化
- sed 命令使用
- 点击div折叠
- JS Math对象中一些小技巧
- Activity Lifecycle
- printf 格式化输出符号详细说明(转)
- WIN8 下 Hyper-V和Vmware Workstation
- Delphi 712操作word
- HDU 3687 National Day Parade (暴力)
- win7系统64位eclipse环境超详细暗黑1.4服务器搭建
- 转:what is TWO_TASK
- [转载]js中__proto__和prototype的区别和关系
- Sqlserver2012数据库乱码的解决方法
- 怎么在网页中加入ICO图标
- 与后台进行连接,mysql模块 第六篇
- HTML5 模拟现实物理效果
- React&;Webpack 环境安装
- 冲刺No.3
- 对于996.ICU这个热门话题,一个在校学生的思考
- 合并排序 java