调试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 ...
随机推荐
- [算法导论]quicksort algorithm @ Python
算法导论上面快速排序的实现. 代码: def partition(array, left, right): i = left-1 for j in range(left, right): if arr ...
- Valid Palindrome leetcode java
题目: Given a string, determine if it is a palindrome, considering only alphanumeric characters and ig ...
- VB.NET,C#.NET调用Web Service,利用visual studio 的实现方法
下面是一篇文章比较详细,其实具体操作很简单,把Web Service服务地址,利用工具(VS2010),通过添加引用的形式,添加到项目中来就可以应用了. 大家如果这个地方不会操场的话,可以问问我QQ: ...
- 两个List合并去重
今天遇到一个合并去重问题,从网上搜索一样总结出来两个比较简单的方法,这里去重是只能取出地址相同的数据,例如:如果两个字符串的值相同但都是单独new出来的这样去不了 @Test public void ...
- 【架构】ServiceMesh初步了解
ServiceMesh初步了解 servicemesh_百度搜索 初识Service Mesh - 原力注入微信公众账号 Service Mesh解读:新一代微服务技术新秀_EAII-企业架构创新研究 ...
- 手动建库时一个错误:Error accessing PRODUCT_USER_PROFILE
首先感谢前辈的文章:http://space.itpub.net/14184018/viewspace-691502 手动创建数据库完成后,创建新用户,并用新用户登陆到数据库时,报错如下: SYS@ ...
- [转]HttpWatch工具简介及使用技巧
http://www.cnblogs.com/mayingbao/archive/2007/11/30/978530.html 一 概述: HttpWatch强大的网页数据分析工具.集成在Intern ...
- Android 7.1.1 之实现 3D Touch
转载请注明出处:http://blog.csdn.net/yyh352091626/article/details/68962736 Shortcut概念 详细实现 BuildConfig 配置 静态 ...
- OpenGL ES 3.0之Fragment buffer objects(FBO)详解(二)
我们可以使用帧缓冲对象来实现离屏渲染.帧缓冲对象支持下列操作 1.只使用OpenGL ES 函数创建帧缓冲区对象. 2.使用EGL context创建多个FBO. 3.创建离屏颜色.深度.模板渲染缓冲 ...
- 5个经典的JavaScript面试题
在IT界中公司对JavaScript开发者的要求还是比较高的,但是如果JavaScript开 发者的技能和经验都达到了一定的级别,那他们还是很容易跳到优秀的公司的,当然薪水就更不是问题了.但是在面试之 ...