
正文
《coredump问题原理探究》Linux x86版7.8节vector相关的iterator对象
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
在前面看过了一个vectorcoredump的样例,接触了vector的iterator,能够知道vector的iterator仅仅有一个成员_M_current指向vector某一个元素.
先看一个样例:
1 #include <vector>
2
3 void init( std::vector<int>& vec )
4 {
5 for ( int i = 0; i < 0x10; i++ )
6 {
7 vec.push_back( i );
8 }
9 }
10
11 int getSum( std::vector<int>& vec )
12 {
13 std::vector<int>::iterator iter;
14 int result = 0;
15
16 for ( iter = vec.begin(); iter != vec.end(); iter++ )
17 {
18 result += *iter;
19 }
20
21 return result;
22 }
23
24 int main()
25 {
26 std::vector<int> vec;
27 init( vec );
28
29 return getSum( vec );
30 }
因为仅仅是考察iterator,仅仅看getSum的汇编:
(gdb) disassemble getSum
Dump of assembler code for function _Z6getSumRSt6vectorIiSaIiEE:
0x080486cd <+0>:push %ebp
0x080486ce <+1>:mov %esp,%ebp
0x080486d0 <+3>:sub $0x38,%esp
0x080486d3 <+6>:lea -0x18(%ebp),%eax
0x080486d6 <+9>:mov %eax,(%esp)
0x080486d9 <+12>:call 0x8048840 <_ZN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEC2Ev>
0x080486de <+17>:movl $0x0,-0xc(%ebp)
0x080486e5 <+24>:lea -0x1c(%ebp),%eax
0x080486e8 <+27>:mov 0x8(%ebp),%edx
0x080486eb <+30>:mov %edx,0x4(%esp)
0x080486ef <+34>:mov %eax,(%esp)
0x080486f2 <+37>:call 0x804884e <_ZNSt6vectorIiSaIiEE5beginEv>
0x080486f7 <+42>:sub $0x4,%esp
0x080486fa <+45>:mov -0x1c(%ebp),%eax
0x080486fd <+48>:mov %eax,-0x18(%ebp)
0x08048700 <+51>:jmp 0x804872f <_Z6getSumRSt6vectorIiSaIiEE+98>
0x08048702 <+53>:lea -0x18(%ebp),%eax
0x08048705 <+56>:mov %eax,(%esp)
0x08048708 <+59>:call 0x80488f8 <_ZNK9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEdeEv>
0x0804870d <+64>:mov (%eax),%eax
0x0804870f <+66>:add %eax,-0xc(%ebp)
0x08048712 <+69>:lea -0x10(%ebp),%eax
0x08048715 <+72>:movl $0x0,0x8(%esp)
0x0804871d <+80>:lea -0x18(%ebp),%edx
0x08048720 <+83>:mov %edx,0x4(%esp)
0x08048724 <+87>:mov %eax,(%esp)
0x08048727 <+90>:call 0x80488c4 <_ZN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEppEi>
0x0804872c <+95>:sub $0x4,%esp
0x0804872f <+98>:lea -0x14(%ebp),%eax
0x08048732 <+101>:mov 0x8(%ebp),%edx
0x08048735 <+104>:mov %edx,0x4(%esp)
0x08048739 <+108>:mov %eax,(%esp)
0x0804873c <+111>:call 0x8048872 <_ZNSt6vectorIiSaIiEE3endEv>
0x08048741 <+116>:sub $0x4,%esp
0x08048744 <+119>:lea -0x14(%ebp),%eax
0x08048747 <+122>:mov %eax,0x4(%esp)
0x0804874b <+126>:lea -0x18(%ebp),%eax
0x0804874e <+129>:mov %eax,(%esp)
0x08048751 <+132>:call 0x8048898 <_ZN9__gnu_cxxneIPiSt6vectorIiSaIiEEEEbRKNS_17__normal_iteratorIT_T0_EESA_>
0x08048756 <+137>:test %al,%al
0x08048758 <+139>:jne 0x8048702 <_Z6getSumRSt6vectorIiSaIiEE+53>
0x0804875a <+141>:mov -0xc(%ebp),%eax
0x0804875d <+144>:leave
0x0804875e <+145>:ret
End of assembler dump.
在0x0804874b打断点.由上面汇编可知,iter的this指针是ebp-0x18,而vec的this指针放在ebp+0x8.
运行到断点处,看一下vec的内容:
(gdb) x $ebp+8
0xbffff5a0:0xbffff5b4
(gdb) x /4x 0xbffff5b4
0xbffff5b4:0x0804b0680x0804b0a80x0804b0a80x080491f0
(gdb) x /16x 0x0804b068
0x804b068:0x000000000x000000010x000000020x00000003
0x804b078:0x000000040x000000050x000000060x00000007
0x804b088:0x000000080x000000090x0000000a0x0000000b
0x804b098:0x0000000c0x0000000d0x0000000e0x0000000f
看一下iter的内容怎样变化,运行完几次c命令之后(注意,断点地址在运行iter++之后):
Breakpoint 1, 0x0804874b in getSum(std::vector<int, std::allocator<int> >&) ()
(gdb) x /4x $ebp-0x18
0xbffff580:0x0804b0680x0804b0a80x000000010x00000000
(gdb) c
Continuing.Breakpoint 1, 0x0804874b in getSum(std::vector<int, std::allocator<int> >&) ()
(gdb) x /4x $ebp-0x18
0xbffff580:0x0804b06c0x0804b0a80x0804b0680x00000000
(gdb) c
Continuing.Breakpoint 1, 0x0804874b in getSum(std::vector<int, std::allocator<int> >&) ()
(gdb) x /4x $ebp-0x18
0xbffff580:0x0804b0700x0804b0a80x0804b06c0x00000001
(gdb) c
Continuing.Breakpoint 1, 0x0804874b in getSum(std::vector<int, std::allocator<int> >&) ()
(gdb) x /4x $ebp-0x18
0xbffff580:0x0804b0740x0804b0a80x0804b0700x00000003
(gdb) c
Continuing.Breakpoint 1, 0x0804874b in getSum(std::vector<int, std::allocator<int> >&) ()
(gdb) x /4x $ebp-0x18
0xbffff580:0x0804b0780x0804b0a80x0804b0740x00000006
可见vector的iterator确实仅仅有一个成员_Ptr,它的取值范围是
vec. _M_start <= _M_current < vec. _M_finish








