调试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 ...
随机推荐
- 大数据开发实战:Stream SQL实时开发三
4.聚合操作 4.1.group by 操作 group by操作是实际业务场景(如实时报表.实时大屏等)中使用最为频繁的操作.通常实时聚合的主要源头数据流不会包含丰富的上下文信息,而是经常需要实时关 ...
- 大数据开发实战:Spark Streaming流计算开发
1.背景介绍 Storm以及离线数据平台的MapReduce和Hive构成了Hadoop生态对实时和离线数据处理的一套完整处理解决方案.除了此套解决方案之外,还有一种非常流行的而且完整的离线和 实时数 ...
- VC++深入详解-第四章学习心得
这一章节主要讲解了 简单的绘图 主要是通过一些小的例子让我们学会了VC++的一些基本操作 void CDrawView::OnLButtonDown(UINT nFlags, CPoint point ...
- http://blog.csdn.net/u014595019/article/details/52805444
http://blog.csdn.net/u014595019/article/details/52805444 tensorflow笔记系列: (一) tensorflow笔记:流程,概念和简单代码 ...
- 【python3】集合set (转)
https://www.cnblogs.com/onepeace/p/4791578.html set原理 Python 还 包 含 了 一 个 数 据 类 型—— set ( 集 合 ) . 集 合 ...
- Cognos11中ActiveReport在移动端的应用
一.环境准备 1.1:前提准备 需要安装了cognos server11,并且已经配置好了服务端 IBM Cognos 版本:IBM Cognos Analytics 11.0.6 IBM Cogno ...
- Install Hyper-V on Windows 10
Enable Hyper-V to create virtual machines on Windows 10.Hyper-V can be enabled in many ways includ ...
- 无法ping通自身
今日,ping localhost 超时,ping 127.0.0.1 显示一般故障.无法访问自己电脑上的tomcat.... 居然,居然是防火墙打开了,关了就好了.我勒个去!!!!
- 扩展一个boot的插件—tooltip&做一个基于boot的表达验证
在线演示 本地下载 (代码太多请查看原文) 加班,加班加班,我爱加班··· 我已经疯了,哦也. 这次发一个刚接触boot的时候用boot做的表单验证,我们扩展一下tooltip的插件,让他可以换颜色. ...
- Creating objects on stack or heap
class Player { private: int health; int strength; int agility; public: void move(); void attackEn ...