C++对象 内存分布
来源:互联网 发布:ubuntu环境变量bashrc 编辑:程序博客网 时间:2024/06/04 18:22
代码如下:
class T { public : T(); virtual int f(void); private : int d; };T::T(void){d = 0x12345678;}int T::f(void){return 12;}void x(T& t) { t.f(); }int main(void){T t;x(t);return 0;}
下面通过汇编来分析类 T 对象的内存分布。
1. 在 main 函数第一行设置断点, 观察执行 T的构造函数之前的情形:
Dump of assembler code for function main(): 0x00010650 <+0>:push{r11, lr} 0x00010654 <+4>:addr11, sp, #4 0x00010658 <+8>:subsp, sp, #8 0x0001065c <+12>:subr3, r11, #12 0x00010660 <+16>:movr0, r3=> 0x00010664 <+20>:bl0x105bc <T::T()> 0x00010668 <+24>:subr3, r11, #12 0x0001066c <+28>:movr0, r3 0x00010670 <+32>:bl0x10624 <x(T&)> 0x00010674 <+36>:movr3, #0 0x00010678 <+40>:b0x10680 <main()+48> 0x0001067c <+44>:bl0x10470 <__cxa_end_cleanup@plt> 0x00010680 <+48>:movr0, r3 0x00010684 <+52>:subsp, r11, #4 0x00010688 <+56>:pop{r11, pc}
此时的栈结构如下:
(gdb) p /x $r0$3 = 0xbefffcc0(gdb) p /x $sp$4 = 0xbefffcc0此时, r0指向 对象 t 在栈上的初始地址(对象 t大小为2字节)。
2.下面进入 T的构造函数:
(gdb) disassDump of assembler code for function T::T(): 0x000105bc <+0>:push{r11}; (str r11, [sp, #-4]!) 0x000105c0 <+4>:addr11, sp, #0 0x000105c4 <+8>:subsp, sp, #12 0x000105c8 <+12>:strr0, [r11, #-8] 0x000105cc <+16>:ldrr3, [r11, #-8] 0x000105d0 <+20>:ldrr2, [pc, #36]; 0x105fc <T::T()+64> 0x000105d4 <+24>:strr2, [r3] 0x000105d8 <+28>:ldrr2, [r11, #-8] 0x000105dc <+32>:movwr3, #22136; 0x5678 0x000105e0 <+36>:movtr3, #4660; 0x1234 0x000105e4 <+40>:strr3, [r2, #4] 0x000105e8 <+44>:ldrr3, [r11, #-8] 0x000105ec <+48>:movr0, r3=> 0x000105f0 <+52>:subsp, r11, #0 0x000105f4 <+56>:pop{r11}; (ldr r11, [sp], #4) 0x000105f8 <+60>:bxlr 0x000105fc <+64>:andeqr0, r1, r0, lsl r7此时,栈上的内容为:
3. 在 x()里面的情形:
Dump of assembler code for function x(T&):=> 0x00010624 <+0>:push{r11, lr} 0x00010628 <+4>:addr11, sp, #4 0x0001062c <+8>:subsp, sp, #8 0x00010630 <+12>:strr0, [r11, #-8] 0x00010634 <+16>:ldrr3, [r11, #-8] 0x00010638 <+20>:ldrr3, [r3] 0x0001063c <+24>:ldrr3, [r3] 0x00010640 <+28>:ldrr0, [r11, #-8] 0x00010644 <+32>:blxr3 0x00010648 <+36>:subsp, r11, #4 0x0001064c <+40>:pop{r11, pc}
(gdb) p /x $sp$20 = 0xbefffcc0(gdb) p /x $r0$21 = 0xbefffcc0(gdb) p /x $r11$22 = 0xbefffccc
Dump of assembler code for function x(T&): 0x00010624 <+0>:push{r11, lr} 0x00010628 <+4>:addr11, sp, #4 0x0001062c <+8>:subsp, sp, #8 0x00010630 <+12>:strr0, [r11, #-8] 0x00010634 <+16>:ldrr3, [r11, #-8] 0x00010638 <+20>:ldrr3, [r3] 0x0001063c <+24>:ldrr3, [r3] 0x00010640 <+28>:ldrr0, [r11, #-8]=> 0x00010644 <+32>:blxr3 0x00010648 <+36>:subsp, r11, #4 0x0001064c <+40>:pop{r11, pc}End of assembler dump.(gdb) p /x $r3$25 = 0x10600(gdb) x $r3 0x10600 <T::f()>:0xe52db004(gdb) p /x $r0$26 = 0xbefffcc0(gdb) x $r0 0xbefffcc0:0x00010710(gdb) x 0x000107100x10710 <_ZTV1T+8>:0x00010600
此时,栈以及调用关系如下:
如前所说, T 占了8个字节,一个4字节是成员变量的,另一个就是vtbl (虚表)指针所占用。这里虚表指向 T::f()的地址。
虚表信息也可以从 gdb观察到:
(gdb) p t$28 = {_vptr.T = 0x10710 <vtable for T+8>, d = 305419896}(gdb) info vtbl tvtable for 'T' @ 0x10710 (subobject @ 0xbefffcc0):[0]: 0x10600 <T::f()>
(gdb) p &t$29 = (T *) 0xbefffcc0
reference:
1. http://blog.httrack.com/blog/2014/05/09/a-basic-glance-at-the-virtual-table/
2.http://www.lrdev.com/lr/c/virtual.html
3.https://cloudfundoo.wordpress.com/2012/04/27/deep-c-understanding-c-object-layout/
0 0
- C++ 对象内存分布
- C++对象内存分布
- C++对象 内存分布
- C语言内存分布
- C程序内存分布
- C/C++内存分布
- c程序内存分布
- C 的内存分布
- C内存分布
- C内存分布
- C内存分布
- c内存分布
- c程序内存分布
- c 内存分布管理
- C语言内存分布
- C内存分布详解
- C语言内存分布
- MyC++之类对象内存分布
- 添加yum 源
- 一种高性能网络游戏服务器架构设计
- DNS相关概念
- 使用面向对象的方式模拟TOM使用ATM进行存取款的操作
- iOS应用崩溃(二)——符号化解析
- C++对象 内存分布
- ez_SQL 单例
- iOS应用崩溃(三)——崩溃日志
- MYECLIPSE 2014 有用的几个快捷键
- Linux有问必答:如何在树莓派上安装USB网络摄像头
- iOS UITableView(二) 为tableView添加数据
- MyBatis Generator generatorConfig.xml配置详解
- C++.OOP
- 手淘双十一系列(一) | 521 性能优化项目揭秘