《coredump问题原理探究》Linux x86版7.1节vector对象

先看一下例子:

1 #include <vector> 2 3 int main() 4 { 5std::vector<int> vec; 6vec.push_back( 0xffeeffab ); 7vec.push_back( 0xabcdef01 ); 8vec.push_back( 0x12345678 ); 9return 0; 10 }

看一下汇编:

(gdb) b mainBreakpoint 1 at 0x8048697(gdb) rStarting program: /home/xuzhina/code/s1/xuzhina_dump_c07_s1 Breakpoint 1, 0x08048697 in main ()Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.149.el6_6.4.i686 libgcc-4.4.7-11.el6.i686 libstdc++-4.4.7-11.el6.i686(gdb) disassemble Dump of assembler code for function main: 0x08048694 <+0>:push %ebp 0x08048695 <+1>:mov %esp,%ebp=> 0x08048697 <+3>:and $0xfffffff0,%esp 0x0804869a <+6>:push %esi 0x0804869b <+7>:push %ebx 0x0804869c <+8>:sub $0x38,%esp 0x0804869f <+11>:lea 0x18(%esp),%eax 0x080486a3 <+15>:mov %eax,(%esp) 0x080486a6 <+18>:call 0x8048740 <_ZNSt6vectorIiSaIiEEC2Ev> 0x080486ab <+23>:movl $0xffeeffab,0x24(%esp) 0x080486b3 <+31>:lea 0x24(%esp),%eax 0x080486b7 <+35>:mov %eax,0x4(%esp) 0x080486bb <+39>:lea 0x18(%esp),%eax 0x080486bf <+43>:mov %eax,(%esp) 0x080486c2 <+46>:call 0x80487b2 <_ZNSt6vectorIiSaIiEE9push_backERKi> 0x080486c7 <+51>:movl $0xabcdef01,0x28(%esp) 0x080486cf <+59>:lea 0x28(%esp),%eax 0x080486d3 <+63>:mov %eax,0x4(%esp) 0x080486d7 <+67>:lea 0x18(%esp),%eax 0x080486db <+71>:mov %eax,(%esp) 0x080486de <+74>:call 0x80487b2 <_ZNSt6vectorIiSaIiEE9push_backERKi> 0x080486e3 <+79>:movl $0x12345678,0x2c(%esp) 0x080486eb <+87>:lea 0x2c(%esp),%eax 0x080486ef <+91>:mov %eax,0x4(%esp) 0x080486f3 <+95>:lea 0x18(%esp),%eax 0x080486f7 <+99>:mov %eax,(%esp) 0x080486fa <+102>:call 0x80487b2 <_ZNSt6vectorIiSaIiEE9push_backERKi> 0x080486ff <+107>:mov $0x0,%ebx 0x08048704 <+112>:lea 0x18(%esp),%eax 0x08048708 <+116>:mov %eax,(%esp) 0x0804870b <+119>:call 0x8048754 <_ZNSt6vectorIiSaIiEED2Ev> 0x08048710 <+124>:mov %ebx,%eax 0x08048712 <+126>:add $0x38,%esp 0x08048715 <+129>:pop %ebx 0x08048716 <+130>:pop %esi 0x08048717 <+131>:mov %ebp,%esp 0x08048719 <+133>:pop %ebp 0x0804871a <+134>:ret0x0804871b <+135>:mov %edx,%ebx 0x0804871d <+137>:mov %eax,%esi 0x0804871f <+139>:lea 0x18(%esp),%eax 0x08048723 <+143>:mov %eax,(%esp) 0x08048726 <+146>:call 0x8048754 <_ZNSt6vectorIiSaIiEED2Ev> 0x0804872b <+151>:mov %esi,%eax 0x0804872d <+153>:mov %ebx,%edx 0x0804872f <+155>:mov %eax,(%esp) 0x08048732 <+158>:call 0x80485c8 <_Unwind_Resume@plt>End of assembler dump.

由0x080486a6,0x080486c2, 0x080486de, 0x080486fa, 0x0804870b地址附近的指令来看,vector的this指针放在esp+0x18.

在0x080486a6,0x080486c2, 0x080486de, 0x080486fa, 0x0804870b打断点来看看this指针所指向的内容如何变化:

在0x080486a6调用的是vector的构造函数:

(gdb) cContinuing.Breakpoint 2, 0x080486a6 in main ()(gdb) x /4x $esp+0x180xbffff248:0xbffff2780x080491090x00210df00x080483a4(gdb) x /4x 0xbffff2780xbffff278:0xbffff2f80x0027ad360x000000010xbffff324(gdb) ni0x080486ab in main ()(gdb) x /4x $esp+0x180xbffff248:0x000000000x000000000x000000000x080483a4

由上可见,一个vector在栈上的占地面积是三个单元.

再看一下第一个push_back之后,vector有什么变化

(gdb) cContinuing.Breakpoint 3, 0x080486c2 in main ()(gdb) x /4x $esp+0x180xbffff248:0x000000000x000000000x000000000xffeeffab(gdb) ni0x080486c7 in main ()(gdb) x /4x $esp+0x180xbffff248:0x0804b0080x0804b00c0x0804b00c0xffeeffab(gdb) x /4x 0x0804b0080x804b008:0xffeeffab0x000000000x000000000x00020ff1

可以看到,vector第一个成员指向的内存0x0804b008刚好放着push_back进来的第一个值0xffeeffab.且vector第二个成员所指向的内存0x0804b00c,与第一个成员刚好差4个字节,和vector里刚好有一个int成员相符.

接着看一下第二个push_back.

(gdb) cContinuing.Breakpoint 4, 0x080486de in main ()(gdb) x /4x $esp+0x180xbffff248:0x0804b0080x0804b00c0x0804b00c0xffeeffab(gdb) ni0x080486e3 in main ()(gdb) x /4x $esp+0x180xbffff248:0x0804b0180x0804b0200x0804b0200xffeeffab(gdb) x /4x 0x0804b0180x804b018:0xffeeffab0xabcdef010x000000000x00020fe1

vector的三个成员的值都有变化.第一个成员由0x0804b008变为0x0804b018,可第一个成员所指向地址的内容却是一样,还是0xffeeffab,而相邻单元放着0xabcdef01,和第二个放入vector的值一样.第二个成员与第一个成员相差8个字节,刚好是2个int字节,和vector拥有2个成员刚好一样.

考察一下第三个push_back:

(gdb) cContinuing.Breakpoint 5, 0x080486fa in main ()(gdb) x /4x $esp+0x180xbffff248:0x0804b0180x0804b0200x0804b0200xffeeffab(gdb) ni0x080486ff in main ()(gdb) x /4x $esp+0x180xbffff248:0x0804b0280x0804b0340x0804b0380xffeeffab(gdb) x /4x 0x0804b0280x804b028:0xffeeffab0xabcdef010x123456780x00000000

仍然可以得到第一个成员指向vector元素的开始,第二个成员是vector元素结束的下一个位置.它们之差与元素大小的商刚好是元素的个数.

如果再考察char,short, long, float, double,数组,结构体,类对象的vector,并结合vector的定义

踮起脚尖,我们就能离幸福更近点吗?

《coredump问题原理探究》Linux x86版7.1节vector对象

相关文章:

你感兴趣的文章:

标签云: