首先需要了解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的更多相关文章

  1. 【原】error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'std::string'

    今天遇到一个非常难以排查的BUG,谷歌度娘都问过了依旧无解,最后自己重新尝试之后找到解决方案: 先看一下报错信息: 1>.\lenz.cpp(2197)  error C2679: binary ...

  2. 【转】标准C++类std::string的内存共享和Copy-On-Write技术

    1.             概念 Scott Meyers在<More Effective C++>中举了个例子,不知你是否还记得?在你还在上学的时候,你的父母要你不要看电视,而去复习功 ...

  3. QString 和std::string互转

    std::string cstr; QString qstring; //****从std::string 到QString qstring = QString(QString::fromLocal8 ...

  4. std::string的split函数

    刚刚要找个按空格分离std::string的函数, 结果发现了stackoverflow上的这个问题. 也没仔细看, 直接拿来一试, 靠, 不对啊, 怎么分离后多出个空字符串, 也就是 "a ...

  5. could not deduce template argument for 'const std::_Tree<_Traits> &' from 'const std::string'

    VS2008, 写一个简单的demo的时候出现了这个: 1>------ Build started: Project: GetExportTable, Configuration: Relea ...

  6. 源码阅读笔记 - 3 std::string 与 Short String Optimization

    众所周知,大部分情况下,操作一个自动(栈)变量的速度是比操作一个堆上的值的速度快的.然而,栈数组的大小是在编译时确定的(不要说 C99 的VLA,那货的 sizeof 是运行时计算的),但是堆数组的大 ...

  7. CString std::string相互转换

    CString->std::string 例子: CString strMfc=“test“; std::string strStl; strStl=strMfc.GetBuffer(0); s ...

  8. 计算std:string的字节长度

    如果项目本身是使用 Unicode 字符集和utf8编码,std::string的length(),size()甚至是c的strLen取到的都是字节长度了,比如三个汉字,就是9, 以上情况不满足的话, ...

  9. 类型安全且自动管理内存的返回 std::string 的 sprintf 实现

    在这篇博文里,我提到了一个例子,说的是使用C++实现类型安全的printf.这个例子很惊艳,但是在我写程序的时候,并非那么"迫切"地需要它出现在我的工具箱中,因为它并不比普通的pr ...

随机推荐

  1. Linux下安装nmap扫描工具

    NMAP是一款流行的网络扫描和嗅探工具,被广泛应用在黑客领域做漏洞探测以及安全扫描,更多的nmap是一个好用的网络工具,在生产和开发中也经常用到,主要做端口开放性检测和局域网信息的查看收集等,不同Li ...

  2. 【Scala】Scala-使用ExecutorService-等待所有线程完成

    Scala-使用ExecutorService-等待所有线程完成 scala ExecutorService 等待_百度搜索 使用ExecutorService,如何等待所有线程完成,?_java_帮 ...

  3. Introduction to Learning to Trade with Reinforcement Learning

    http://www.wildml.com/2015/12/implementing-a-cnn-for-text-classification-in-tensorflow/ The academic ...

  4. PHP使用DOM XML操作XML[总结]

    1.前言 XML树状层次结构鲜明,非常适合作为配置文件.PHP中可以使用DOM XML来操作XML.本文总结一下PHP使用DOM XML创建.添加节点.查询XML文件. 2.使用DOM XML XML ...

  5. paypal 的IPN通知调用出错

    一直报错: 当本地curl需要访问https时,出现SSL certificate: unable to get local issuer certificate错误信息 解决办法: 到http:// ...

  6. Python在VSCode中进入交互界面调试

    VSCode非常强大,断点好用,美中不足,每次只能通过下面窄窄一行进行各种检查,而python的优点就在于交互式的调试,所以希望能够在断点时能够进入到正常的交互界面进行调试. 我用的插件是: 设置交互 ...

  7. vc2008中mfc菜单、控件等汉字显示为问号或乱码的解决方法

    在vc2008中建立基于mfc的project.在向导的Application type页面中如果在resource language选项中选择"英语(美国)"(图一),那么在pr ...

  8. MFC中调用web api

    使用COM组件来调用,需要catch com error. IXMLHTTPRequestPtr pIXMLHTTPRequest = NULL; BSTR bstrString = NULL; HR ...

  9. Horizon Is Easy, Horizon Is Complex

    本文出自我的同事兼基友@monsterxx03 之手,本人稍作润色 Horizon Is Easy, Horizon Is Complex 如果要用一句话来概括Openstack Dashboard项 ...

  10. 用一条sql取得第10到第20条的记录

    因为id可能不是连续的,所以不能用取得10<id<20的记录的方法. 有三种方法可以实现:一.搜索前20条记录,指定不包括前10条语句:select top 20 * from tbl w ...