调试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。
调试std::string的更多相关文章
- 【原】error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'std::string'
今天遇到一个非常难以排查的BUG,谷歌度娘都问过了依旧无解,最后自己重新尝试之后找到解决方案: 先看一下报错信息: 1>.\lenz.cpp(2197) error C2679: binary ...
- 【转】标准C++类std::string的内存共享和Copy-On-Write技术
1. 概念 Scott Meyers在<More Effective C++>中举了个例子,不知你是否还记得?在你还在上学的时候,你的父母要你不要看电视,而去复习功 ...
- QString 和std::string互转
std::string cstr; QString qstring; //****从std::string 到QString qstring = QString(QString::fromLocal8 ...
- std::string的split函数
刚刚要找个按空格分离std::string的函数, 结果发现了stackoverflow上的这个问题. 也没仔细看, 直接拿来一试, 靠, 不对啊, 怎么分离后多出个空字符串, 也就是 "a ...
- could not deduce template argument for 'const std::_Tree<_Traits> &' from 'const std::string'
VS2008, 写一个简单的demo的时候出现了这个: 1>------ Build started: Project: GetExportTable, Configuration: Relea ...
- 源码阅读笔记 - 3 std::string 与 Short String Optimization
众所周知,大部分情况下,操作一个自动(栈)变量的速度是比操作一个堆上的值的速度快的.然而,栈数组的大小是在编译时确定的(不要说 C99 的VLA,那货的 sizeof 是运行时计算的),但是堆数组的大 ...
- CString std::string相互转换
CString->std::string 例子: CString strMfc=“test“; std::string strStl; strStl=strMfc.GetBuffer(0); s ...
- 计算std:string的字节长度
如果项目本身是使用 Unicode 字符集和utf8编码,std::string的length(),size()甚至是c的strLen取到的都是字节长度了,比如三个汉字,就是9, 以上情况不满足的话, ...
- 类型安全且自动管理内存的返回 std::string 的 sprintf 实现
在这篇博文里,我提到了一个例子,说的是使用C++实现类型安全的printf.这个例子很惊艳,但是在我写程序的时候,并非那么"迫切"地需要它出现在我的工具箱中,因为它并不比普通的pr ...
随机推荐
- a标签置灰不可点击
a标签的title属性可以实现鼠标放上去显示信息的功能 <a title="编辑" href ="javascript:return false;" on ...
- 【Spark】SparkStreaming-提交到集群运行
SparkStreaming-提交到集群运行 spark streaming 提交_百度搜索 SparkStreaming示例在集群中运行 - CSDN博客
- ORACLE中union/union all/Intersect/Minus用法
Union,对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序: Union All,对两个结果集进行并集操作,包括重复行,不进行排序: Intersect,对两个结果集进行交集操作,不包 ...
- 【应用】R--判断类别型属性之间是否有相关性(相互之间是否独立)
检验某学区所有在售房源中,小区与楼栋类别(低层:多层;小高层:高层)是否相关 导入数据: > house<- read.table("house_data.txt", ...
- 解决eclipse导出javadoc时的“错误: 编码GBK的不可映射字符”问题(转)
http://blog.csdn.net/psy1100/article/details/51179342 今天要将自己的API接口和MODEL导出来一份java doc参考文档, 但是在导出的时候却 ...
- Github上Stars最多的53个深度学习项目,TensorFlow遥遥领先
原文:https://github.com/aymericdamien/TopDeepLearning 项目名称 Stars 项目介绍 TensorFlow 29622 使用数据流图计算可扩展机器学习 ...
- 主成分分析(PCA)原理及推导
原文:http://blog.csdn.net/zhongkejingwang/article/details/42264479 什么是PCA? 在数据挖掘或者图像处理等领域经常会用到主成分分析,这样 ...
- JavaScript 从闭包可以做什么开始,将有助于理解闭包
本文内容 函数内部访问全局变量 函数外部不能直接访问局部变量 函数外部访问局部变量 保护私有成员 持久性 模块化 抽象性 闭包是 JavaScript 的重要特性,非常强大,可用于执行复杂的计算,可并 ...
- Iperf是一个网络性能测试工具
http://blog.163.com/hlz_2599/blog/static/142378474201341341339314/ Iperf是一个网络性能测试工具.Iperf可以测试TCP和UDP ...
- PYQT实现简单的浏览器功能
主要的类 QMainWindow 提供一个有菜单条.锚接窗口(例如工具条)和一个状态条的主应用程序窗口. http://www.kuqin.com/qtdocument/qmainwindow.htm ...