《coredump问题原理探究》Linux x86版7.11节string对象
2015-11-24 22:51
676 查看
在定位map coredump的那一节已经接触了string对象.在这里重温一下.
看一个例子:
看一下汇编:
在0x080485bc打断点.
由上面汇编可知,esp+0x14是string对象的this指针, 字符串”hello world”放在esp+0x18.
构造完毕的string对象
由_ZNSs4_Rep20_S_empty_rep_storageE+12这一行,我们看一下把string对象的this指针-12,看看内容是怎样?
看不出什么东西。
调用第一次append后.
由于字符串”helloworld!”的大小是12(0xc),而0x804a008开始的两个单元都是0xc,究竟哪一个才是实际大小。而0x0804a014所存放的就是”hello world!”.
看一下多调用几次append之后会怎样:
可见,string对象有如下特征:
1. 第一个成员是字符串大小
2. 第二个成员是字符串对象的最大空间
3. 第四个成员存放着字符串
4. 当字符串的大小超过对象最大空间时,字符串对象会重新分配一段连续内存。
5. 当字符串对象刚刚构造完成时,并没有分配任何空间。
看一个例子:
1 #include <string> 2 #include <stdio.h> 3 4 int main() 5 { 6 std::string str; 7 char* ptr = "hello world!"; 8 9 for ( int i = 0; i < 0x10; i++ ) 10 { 11 str.append( ptr ); 12 } 13 14 return 0; 15 }
看一下汇编:
(gdb) disassemble main Dump of assembler code for function main: 0x08048584 <+0>: push %ebp 0x08048585 <+1>: mov %esp,%ebp 0x08048587 <+3>: and $0xfffffff0,%esp 0x0804858a <+6>: push %esi 0x0804858b <+7>: push %ebx 0x0804858c <+8>: sub $0x28,%esp 0x0804858f <+11>: lea 0x14(%esp),%eax 0x08048593 <+15>: mov %eax,(%esp) 0x08048596 <+18>: call 0x8048460 <_ZNSsC1Ev@plt> 0x0804859b <+23>: movl $0x80486d4,0x18(%esp) 0x080485a3 <+31>: movl $0x0,0x1c(%esp) 0x080485ab <+39>: jmp 0x80485c6 <main+66> 0x080485ad <+41>: mov 0x18(%esp),%eax 0x080485b1 <+45>: mov %eax,0x4(%esp) 0x080485b5 <+49>: lea 0x14(%esp),%eax 0x080485b9 <+53>: mov %eax,(%esp) 0x080485bc <+56>: call 0x80484a0 <_ZNSs6appendEPKc@plt> 0x080485c1 <+61>: addl $0x1,0x1c(%esp) 0x080485c6 <+66>: cmpl $0xf,0x1c(%esp) 0x080485cb <+71>: setle %al 0x080485ce <+74>: test %al,%al 0x080485d0 <+76>: jne 0x80485ad <main+41> 0x080485d2 <+78>: mov $0x0,%ebx 0x080485d7 <+83>: lea 0x14(%esp),%eax 0x080485db <+87>: mov %eax,(%esp) 0x080485de <+90>: call 0x8048490 <_ZNSsD1Ev@plt> 0x080485e3 <+95>: mov %ebx,%eax 0x080485e5 <+97>: add $0x28,%esp 0x080485e8 <+100>: pop %ebx 0x080485e9 <+101>: pop %esi 0x080485ea <+102>: mov %ebp,%esp 0x080485ec <+104>: pop %ebp 0x080485ed <+105>: ret 0x080485ee <+106>: mov %edx,%ebx 0x080485f0 <+108>: mov %eax,%esi 0x080485f2 <+110>: lea 0x14(%esp),%eax 0x080485f6 <+114>: mov %eax,(%esp) 0x080485f9 <+117>: call 0x8048490 <_ZNSsD1Ev@plt> 0x080485fe <+122>: mov %esi,%eax 0x08048600 <+124>: mov %ebx,%edx 0x08048602 <+126>: mov %eax,(%esp) 0x08048605 <+129>: call 0x80484c0 <_Unwind_Resume@plt> End of assembler dump.
在0x080485bc打断点.
由上面汇编可知,esp+0x14是string对象的this指针, 字符串”hello world”放在esp+0x18.
构造完毕的string对象
(gdb) x /wx $esp+0x14 0xbffff664: 0x00d2ff5c (gdb) x /8wx 0x00d2ff5c 0xd2ff5c <_ZNSs4_Rep20_S_empty_rep_storageE+12>: 0x00000000 0x00000000 0x00000000 0x00000000 0xd2ff6c <_ZNSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE2idE>: 0x00000000 0x00000000 0x00000000 0x00000000
由_ZNSs4_Rep20_S_empty_rep_storageE+12这一行,我们看一下把string对象的this指针-12,看看内容是怎样?
(gdb) x /8wx 0x00d2ff5c-0xc 0xd2ff50 <_ZNSs4_Rep20_S_empty_rep_storageE>: 0x00000000 0x00000000 0x00000000 0x00000000 0xd2ff60 <_ZNSt10moneypunctIwLb0EE2idE>: 0x00000000 0x00000000 0x00000000 0x00000000
看不出什么东西。
调用第一次append后.
(gdb) ni 0x080485c1 in main () (gdb) x /wx $esp+0x14 0xbffff664: 0x0804a014 (gdb) x /8wx 0x0804a014 0x804a014: 0x6c6c6568 0x6f77206f 0x21646c72 0x00000000 0x804a024: 0x00020fe1 0x00000000 0x00000000 0x00000000 (gdb) x /8wx 0x0804a014-0xc 0x804a008: 0x0000000c 0x0000000c 0x00000000 0x6c6c6568 0x804a018: 0x6f77206f 0x21646c72 0x00000000 0x00020fe1
由于字符串”helloworld!”的大小是12(0xc),而0x804a008开始的两个单元都是0xc,究竟哪一个才是实际大小。而0x0804a014所存放的就是”hello world!”.
看一下多调用几次append之后会怎样:
(gdb) c Continuing. Breakpoint 1, 0x080485bc in main () (gdb) ni 0x080485c1 in main () (gdb) x /wx $esp+0x14 0xbffff664: 0x0804a034 (gdb) x /8wx 0x0804a034-0xc 0x804a028: 0x00000018 0x00000018 0x00000000 0x6c6c6568 0x804a038: 0x6f77206f 0x21646c72 0x6c6c6568 0x6f77206f (gdb) c Continuing. Breakpoint 1, 0x080485bc in main () (gdb) ni 0x080485c1 in main () (gdb) x /wx $esp+0x14 0xbffff664: 0x0804a064 (gdb) x /16wx 0x0804a064-0xc 0x804a058: 0x00000024 0x00000030 0x00000000 0x6c6c6568 0x804a068: 0x6f77206f 0x21646c72 0x6c6c6568 0x6f77206f 0x804a078: 0x21646c72 0x6c6c6568 0x6f77206f 0x21646c72 0x804a088: 0x00000000 0x00000000 0x00000000 0x00000000 (gdb) c Continuing. Breakpoint 1, 0x080485bc in main () (gdb) ni 0x080485c1 in main () (gdb) x /wx $esp+0x14 0xbffff664: 0x0804a064 (gdb) x /16wx 0x0804a064-0xc 0x804a058: 0x00000030 0x00000030 0x00000000 0x6c6c6568 0x804a068: 0x6f77206f 0x21646c72 0x6c6c6568 0x6f77206f 0x804a078: 0x21646c72 0x6c6c6568 0x6f77206f 0x21646c72 0x804a088: 0x6c6c6568 0x6f77206f 0x21646c72 0x00000000 (gdb) c Continuing. Breakpoint 1, 0x080485bc in main () (gdb) ni 0x080485c1 in main () (gdb) x /wx $esp+0x14 0xbffff664: 0x0804a0ac (gdb) x /16wx 0x0804a0ac-0xc 0x804a0a0: 0x0000003c 0x00000060 0x00000000 0x6c6c6568 0x804a0b0: 0x6f77206f 0x21646c72 0x6c6c6568 0x6f77206f 0x804a0c0: 0x21646c72 0x6c6c6568 0x6f77206f 0x21646c72 0x804a0d0: 0x6c6c6568 0x6f77206f 0x21646c72 0x6c6c6568
可见,string对象有如下特征:
1. 第一个成员是字符串大小
2. 第二个成员是字符串对象的最大空间
3. 第四个成员存放着字符串
4. 当字符串的大小超过对象最大空间时,字符串对象会重新分配一段连续内存。
5. 当字符串对象刚刚构造完成时,并没有分配任何空间。
相关文章推荐
- linux 下solr
- Linux 下源码安装大杂烩
- Linux Advance--打印标准IO流缓冲状态信息
- 在centos6.6上安装guacamole 0.9.8
- Linux socat命令
- 中午游泳很海皮-linux&php
- Linux下安装g++编译器心得
- [Linux] Enable ssh key authentication from one user on client to multiple users on server
- Linux 非缓冲I/O与缓冲I/O
- Centos的管理工具---Security_FX 中文乱码处理
- awk学习
- CentOS Linux 监控安装之cacti
- linux文件按最新时间排序
- linux下用rpm 安装jdk
- 内核阅读笔记之浅析Linux2.6.34内核桥接数据转发(一)
- 成为一名嵌入式Linux开发工程师需要学习哪些知识?
- Linux Network Device Name issue
- linux下利用系统函数实现rm -rf的功能!
- Linux下Vsftp配置及详解
- Linux进程冻结技术