开发的时候,遇到一个问题vector中的对象在使用的时候被析构了,看代码无法理解,没啥说的,gdb跟踪。但是print vector变量智能打印地址,怎么展示对象的内容呢?
(gdb) p second
$2 = {<std::_Vector_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {
_M_impl = {<std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >> = {<__gnu_cxx::new_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >> = {<No data fields>}, <No data fields>}, <std::_Vector_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_Vector_impl_data> = {_M_start = 0x618c70, _M_finish = 0x618cb0, _M_end_of_storage = 0x618cb0}, <No data fields>}}, <No data fields>}
网上查阅,下帖,作者自己写的工具可以实现打印。gdb中 source这个工具文件,就可以使用工具。
http://blog.chinaunix.net/uid-25006789-id-3945673.html
分析脚本工具,核心脚本如下:
set $size = $arg0._M_impl._M_finish - $arg0._M_impl._M_start
set $capacity = $arg0._M_impl._M_end_of_storage - $arg0._M_impl._M_start
set $size_max = $size - 1
set $i = 0
while $i < $size
printf "elem[%u]: ", $i
p *($arg0._M_impl._M_start + $i)
set $i++
end
## 尝试,确实可以
(gdb) p *(second._M_impl->_M_start)
$14 = {
static npos = 18446744073709551615,
_M_dataplus = {
<std::allocator<char>> = {
<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>},
members of std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Alloc_hider:
_M_p = 0x618c80 "bcd"
},
_M_string_length = 3,
{
_M_local_buf = "bcd\000\377\177\000\000 \177\335\367\377\177\000",
_M_allocated_capacity = 140733199967074
}
}
(gdb) p *(second._M_impl->_M_start+1)
$15 = {
static npos = 18446744073709551615,
_M_dataplus = {
<std::allocator<char>> = {
<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>},
members of std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Alloc_hider:
_M_p = 0x618ca0 "cde"
},
_M_string_length = 3,
{
_M_local_buf = "cde\000\000\000\000\000I/\025\367\377\177\000",
_M_allocated_capacity = 6644835
}
}
这不就是带类型的指针 或者数组概念嘛。感觉之前对数组指针没有理解到位,看stl源码,虽然_M_impl._M_finish 、_M_impl._M_start是两个带类型的指针,编译器可以根据类型计算出对象数量。
用char和int写demo验证,代码及结果如下
#include<iostream>
using namespace std;
#include<vector>
#include <cstring>
int main()
{
char test2[] = {"abcdefabcdefabcdef"};
std::cout << "char* type test2 len: " << strlen(test2) << std::endl;
char* test2_end = test2+strlen(test2);
std::cout << "test2 size: " << (test2_end - test2) << std::endl;
int *test3 = (int*)test2;
int* test3_end = test3+((test2_end - test2)/4==0?(test2_end - test2)/4:(test2_end - test2)/4+1 );
std::cout << "test3 size: " << (test3_end - test3) << std::endl;
getchar();
return 0;
}
char* type test2 len: 18
test2 size: 18 // 字符18个
test3 size: 5 // int类型数量5个
(gdb) p test3
$1 = (int *) 0x7fffffffe2e0
(gdb) p test3_end
$2 = (int *) 0x7fffffffe2f4
(gdb) p 0x7fffffffe2f4 -0x7fffffffe2e0
$3 = 20
(gdb) p test3_end -test3
$4 = 5
(gdb)
总结下,vector可以用如下方法打印
(gdb) p second
$2 = {<std::_Vector_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {
_M_impl = {<std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >> = {<__gnu_cxx::new_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >> = {<No data fields>}, <No data fields>}, <std::_Vector_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_Vector_impl_data> = {_M_start = 0x618c70, _M_finish = 0x618cb0, _M_end_of_storage = 0x618cb0}, <No data fields>}}, <No data fields>}
(gdb) p second._M_impl->_M_start
$3 = (std::_Vector_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::pointer) 0x618c70
(gdb) p *(std::_Vector_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::pointer) 0x618c70
$4 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x618c80 "bcd"}, _M_string_length = 3, {
_M_local_buf = "bcd\000\377\177\000\000\000\252\260\367\377\177\000", _M_allocated_capacity = 140733199967074}}
(gdb) p *(second._M_impl->_M_start)
$5 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x618c80 "bcd"}, _M_string_length = 3, {
_M_local_buf = "bcd\000\377\177\000\000\000\252\260\367\377\177\000", _M_allocated_capacity = 140733199967074}}
(gdb)