《coredump问题原理探究》Linux x86版7.3节List对象
先看一下例子:
1 #include <list> 2 3 int main() 4 { 5 std::list<int> lst; 6 7 lst.push_back( 0x12345678 ); 8 lst.push_front( 0xabcdef01 ); 9 lst.push_back( 0x24242522 ); 10 11 return 0; 12 }
再看一下汇编:
(gdb) disassemble main Dump of assembler code for function main: 0x080485b4 <+0>: push %ebp 0x080485b5 <+1>: mov %esp,%ebp 0x080485b7 <+3>: and $0xfffffff0,%esp 0x080485ba <+6>: push %esi 0x080485bb <+7>: push %ebx 0x080485bc <+8>: sub $0x38,%esp 0x080485bf <+11>: lea 0x1c(%esp),%eax 0x080485c3 <+15>: mov %eax,(%esp) 0x080485c6 <+18>: call 0x8048674 <_ZNSt4listIiSaIiEEC2Ev> 0x080485cb <+23>: movl $0x12345678,0x24(%esp) 0x080485d3 <+31>: lea 0x24(%esp),%eax 0x080485d7 <+35>: mov %eax,0x4(%esp) 0x080485db <+39>: lea 0x1c(%esp),%eax 0x080485df <+43>: mov %eax,(%esp) 0x080485e2 <+46>: call 0x80486de <_ZNSt4listIiSaIiEE9push_backERKi> 0x080485e7 <+51>: movl $0xabcdef01,0x28(%esp) 0x080485ef <+59>: lea 0x28(%esp),%eax 0x080485f3 <+63>: mov %eax,0x4(%esp) 0x080485f7 <+67>: lea 0x1c(%esp),%eax 0x080485fb <+71>: mov %eax,(%esp) 0x080485fe <+74>: call 0x8048714 <_ZNSt4listIiSaIiEE10push_frontERKi> 0x08048603 <+79>: movl $0x24242522,0x2c(%esp) 0x0804860b <+87>: lea 0x2c(%esp),%eax 0x0804860f <+91>: mov %eax,0x4(%esp) ---Type <return> to continue, or q <return> to quit--- 0x08048613 <+95>: lea 0x1c(%esp),%eax 0x08048617 <+99>: mov %eax,(%esp) 0x0804861a <+102>: call 0x80486de <_ZNSt4listIiSaIiEE9push_backERKi> 0x0804861f <+107>: mov $0x0,%ebx 0x08048624 <+112>: lea 0x1c(%esp),%eax 0x08048628 <+116>: mov %eax,(%esp) 0x0804862b <+119>: call 0x8048660 <_ZNSt4listIiSaIiEED2Ev> 0x08048630 <+124>: mov %ebx,%eax 0x08048632 <+126>: add $0x38,%esp 0x08048635 <+129>: pop %ebx 0x08048636 <+130>: pop %esi 0x08048637 <+131>: mov %ebp,%esp 0x08048639 <+133>: pop %ebp 0x0804863a <+134>: ret 0x0804863b <+135>: mov %edx,%ebx 0x0804863d <+137>: mov %eax,%esi 0x0804863f <+139>: lea 0x1c(%esp),%eax 0x08048643 <+143>: mov %eax,(%esp) 0x08048646 <+146>: call 0x8048660 <_ZNSt4listIiSaIiEED2Ev> 0x0804864b <+151>: mov %esi,%eax 0x0804864d <+153>: mov %ebx,%edx 0x0804864f <+155>: mov %eax,(%esp) 0x08048652 <+158>: call 0x80484e8 <_Unwind_Resume@plt> End of assembler dump.
由0x080485c6附近的汇编来看,this指针放在esp+0x1c
在0x080485c6, 0x080485e2,0x080485fe, 0x0804861a, 0x0804862b打断点
(gdb) b *0x080485c6 Breakpoint 1 at 0x80485c6 (gdb) b *0x080485e2 Breakpoint 2 at 0x80485e2 (gdb) b *0x080485fe Breakpoint 3 at 0x80485fe (gdb) b *0x0804861a Breakpoint 4 at 0x804861a (gdb) b *0x0804862b Breakpoint 5 at 0x804862b
先看一下list运行构造函数后会怎样.
Breakpoint 1, 0x080485c6 in main () (gdb) x /8x $esp+0x1c 0xbffff24c: 0x08048aa9 0x028ea550 0x0804832e 0x00000000 0xbffff25c: 0x009faff4 0x08048a90 0x08048500 0x009faff4 (gdb) ni 0x080485cb in main () (gdb) x /8x $esp+0x1c 0xbffff24c: 0xbffff24c 0xbffff24c 0x0804832e 0x00000000 0xbffff25c: 0x009faff4 0x08048a90 0x08048500 0x009faff4
可以看出list对象有两个成员, 且这两个成员的值均指向自身。可见,这两个成员是指针。
再看一下第一个push_back后
Breakpoint 2, 0x080485e2 in main () (gdb) x /8x $esp+0x1c 0xbffff24c: 0xbffff24c 0xbffff24c 0x12345678 0x00000000 0xbffff25c: 0x009faff4 0x08048a90 0x08048500 0x009faff4 (gdb) ni 0x080485e7 in main () (gdb) x /8x $esp+0x1c 0xbffff24c: 0x0804b008 0x0804b008 0x12345678 0x00000000 0xbffff25c: 0x009faff4 0x08048a90 0x08048500 0x009faff4 (gdb) x /8x 0x0804b008 0x804b008: 0xbffff24c 0xbffff24c 0x12345678 0x00020ff1 0x804b018: 0x00000000 0x00000000 0x00000000 0x00000000
用结构表示如下:
再看一下push_front
Breakpoint 3, 0x080485fe in main () (gdb) x /8x $esp+0x1c 0xbffff24c: 0x0804b008 0x0804b008 0x12345678 0xabcdef01 0xbffff25c: 0x009faff4 0x08048a90 0x08048500 0x009faff4 (gdb) x /8x 0x0804b008 0x804b008: 0xbffff24c 0xbffff24c 0x12345678 0x00020ff1 0x804b018: 0x00000000 0x00000000 0x00000000 0x00000000 (gdb) ni 0x08048603 in main () (gdb) x /8x $esp+0x1c 0xbffff24c: 0x0804b018 0x0804b008 0x12345678 0xabcdef01 0xbffff25c: 0x009faff4 0x08048a90 0x08048500 0x009faff4 (gdb) x /8x 0x0804b018 0x804b018: 0x0804b008 0xbffff24c 0xabcdef01 0x00020fe1 0x804b028: 0x00000000 0x00000000 0x00000000 0x00000000 (gdb) x /8x 0x0804b008 0x804b008: 0xbffff24c 0x0804b018 0x12345678 0x00000011 0x804b018: 0x0804b008 0xbffff24c 0xabcdef01 0x00020fe1
用图形来表示就如下(只表示第一个成员).
如果考察这三个地址的第二个成员,就会变成这样的图形
同样考察第二个push_back,并参照list的代码,会得到这样的结论.
1. list有两个成员,第一个成员指向链表的头部,第二个成员指向链表的尾部
2. 链表的每一个节点都有三个元素,第一个_M_next,指向下一个节点.第二个_M_prev指向前一个节点.第三个_M_data存储节点的值.
3. list所指向的链表每一个节点的_M_next, _M_prev指针应该都不为空的,也必须是指向有效地址.
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。