编译时,指定宏 _GLIBCXX_DEBUG 即以 Debug 方式使用 STL 库,效果如下:
#include <string>
#include <stdio.h>
int main(int argc, char* argv[]) {
std::string str;
str = "123";
printf("(%zd)%s\n", str.size(), str.c_str());
return 0;
}
$ g++ -D_GLIBCXX_DEBUG -std=c++11 -g -o x x.cpp
(gdb) b basic_string.h:207
(gdb) bt
#0 std::string::_Rep::_M_set_length_and_sharable (this=0x604010, __n=3) at /usr/include/c++/4.8.2/bits/basic_string.h:210
#1 0x0000000000401c66 in std::string::_M_mutate (this=0x7fffffffe490, __pos=0, __len1=0, __len2=3) at /usr/include/c++/4.8.2/bits/basic_string.tcc:496
#2 0x0000000000401900 in std::string::_M_replace_safe (this=0x7fffffffe490, __pos1=0, __n1=0, __s=0x401f11 "123", __n2=3) at /usr/include/c++/4.8.2/bits/basic_string.tcc:684
#3 0x00000000004016d7 in std::string::assign (this=0x7fffffffe490, __s=0x401f11 "123", __n=3) at /usr/include/c++/4.8.2/bits/basic_string.tcc:264
#4 0x00000000004015c4 in std::string::assign (this=0x7fffffffe490, __s=0x401f11 "123") at /usr/include/c++/4.8.2/bits/basic_string.h:1131
#5 0x0000000000401449 in std::string::operator= (this=0x7fffffffe490, __s=0x401f11 "123") at /usr/include/c++/4.8.2/bits/basic_string.h:555
#6 0x0000000000401215 in main (argc=1, argv=0x7fffffffe598) at x.cpp:5
(gdb) l
205
206 void
207 _M_set_length_and_sharable(size_type __n)
208 {
209 #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
210 if (__builtin_expect(this != &_S_empty_rep(), false))
211 #endif
212 {
213 this->_M_set_sharable(); // One reference.
214 this->_M_length = __n;
typedef basic_string<char> string;
basic_string<_CharT, _Traits, _Alloc>::_Rep::_S_max_size = (((npos - sizeof(_Rep_base))/sizeof(_CharT)) - 1) / 4;
basic_string<_CharT, _Traits, _Alloc>::_Rep::_S_terminal = _CharT(); // 结尾符号,对于 char 实为 0
struct _Rep_base
{
// _M_length:字符串长度
// 注意:不一定是字节数,
// 和 _CharT 的类型有关,如果为 char 则为字节数
size_type _M_length;
size_type _M_capacity;
_Atomic_word _M_refcount; // 引用计数
};
struct _Rep: _Rep_base
{
static const size_type _S_max_size;
static const _CharT _S_terminal;
void _M_set_sharable()
{
this->_M_refcount = 0;
}
void _M_set_length_and_sharable(size_type __n)
{
#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
if (__builtin_expect(this != &_S_empty_rep(), false))
#endif
{
this->_M_set_sharable(); // One reference. // 置引用计数为 0
this->_M_length = __n; // 设置长度(不包含任何空结尾符)
traits_type::assign(this->_M_refdata()[__n], _S_terminal); // 添加空结尾符(null terminated char)
// grrr. (per 21.3.4)
// You cannot leave those LWG people alone for a second.
}
}
_CharT* _M_refdata() throw()
{
return reinterpret_cast<_CharT*>(this + 1); // 实际指向 _Alloc_hider::_M_p
}
};
struct _Alloc_hider: _Alloc
{
_CharT* _M_p; // The actual data.
};
template<typename _CharT, typename _Traits, typename _Alloc>
class basic_string
{
static const size_type npos = static_cast<size_type>(-1);
mutable _Alloc_hider _M_dataplus;
// 返回不包含任何空结尾符的字符个数
// Returns the number of characters in the string, not including any null-termination.
size_type size() const
{
return _M_rep()->_M_length;
}
_CharT* _M_data() const
{
return _M_dataplus._M_p;
}
_Rep* _M_rep() const
{
return &((reinterpret_cast<_Rep*> (_M_data()))[-1]); // 在 _M_refdata() 中使用时 +1
}
basic_string& assign(const _CharT* __s)
{
__glibcxx_requires_string(__s);
return this->assign(__s, traits_type::length(__s));
}
template<typename _CharT, typename _Traits, typename _Alloc>
basic_string<_CharT, _Traits, _Alloc>&
basic_string<_CharT, _Traits, _Alloc>::assign(const _CharT* __s, size_type __n)
{
__glibcxx_requires_string_len(__s, __n);
_M_check_length(this->size(), __n, "basic_string::assign");
if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
{
return _M_replace_safe(size_type(0), this->size(), __s, __n);
}
else
{
// Work in-place.
const size_type __pos = __s - _M_data();
if (__pos >= __n)
_M_copy(_M_data(), __s, __n);
else if (__pos)
_M_move(_M_data(), __s, __n);
_M_rep()->_M_set_length_and_sharable(__n);
return *this;
}
}
};
|