gdb x命令_gdb分析C++对象内存布局(一)

7dc605b581cef00d52794639f14d1308.png

gdb分析C++对象内存布局(二):https://zhuanlan.zhihu.com/p/90770282

本文分析如下2个场景:

  • 没有虚函数的类之间实现单继承;
  • 有虚函数的类之间实现单继承。

单继承指的是派生类只继承一个基类。虚函数则是实现C++类对象多态的机制。

没有虚函数的类之间实现单继承

以下代码是没有虚函数的类之间实现单继承。

其中,代码(5)生成的对象的类跟要赋值的指针对应的类是不同的,指针对应的类是生成对象的类的基类,这种赋值操作称为upcast。

// hierarchy_test.cpp

对以上代码执行g++ -o hierarchy_test hierarchy_test.cpp -g -std=c++11进行编译。其中,-g参数使生成的可执行程序可以通过gdb进行调试。

执行./hierarchy_test后,输出如下。

(A
  • 只有成员变量会占用类对象的内存空间,成员函数不占用。
  • 经过upcast后的基类指针指向的地址与派生类指针指向的地址是一样的。
  • 调用成员函数是根据调用者的类类型决定,也就是说,调用者是基类指针,则调用基类对应的成员函数,调用者是派生类指针,则调用派生类对应的成员函数。

有虚函数的类之间实现单继承

以下代码是有虚函数的类之间实现单继承。

// virtual_hierarchy_test.cpp

对以上代码执行g++ -o virtual_hierarchy_test virtual_hierarchy_test.cpp -g -std=c++11进行编译。

执行./virtual_hierarchy_test后,输出如下。

(A
  • 除了成员函数会占用类对象的内存空间,还另外有一个指向虚函数表的虚函数表指针(vptr)会占用内存空间,且为了对齐,类对象的内存空间是8的倍数。
  • 经过upcast后的基类指针指向的地址与派生类指针指向的地址是一样的。
  • 调用成员虚函数是根据被调用者本身的类类型决定,也就是说,不管调用者的类类型是什么,最终调用的是被调用者对应的虚函数表里的函数,这就是虚函数的作用,虚函数实现了派生类的多态。

生成的派生类的对象内存布局如下。派生类的生成过程为:首先调用基类的构造函数,此时对象的虚函数表指针指向基类的虚函数表,接着调用派生类的构造函数,此时,一方面,“覆盖”原来的虚函数表指针,使指针指向派生类的虚函数表,另外一方面,增加派生类自己的成员变量到新生成的对象中。

6ccc1413fe533ce68b7efd0cd06288f6.png

通过gdb调试的方法验证生成的对象的内存布局。

对生成的可执行程序执行gdb virtual_hierarchy_test,设置break(断点设置在return语句处)并执行run之后,就可以对生成的对象的内存布局进行分析。

分析前先在gdb环境下执行如下命令,让内存空间的数据更具可读性。

(gdb

之后执行如下命令。

(gdb

根据输出结果分析如下:

  • 0x614c20是派生类生成的对象d的起始地址,通过x/2xg 0x614c20可以获得该对象的内存空间数据,其中,0x0000000000400d10是虚函数表指针_vptr.A所保存的派生类的虚函数表的地址,0x000000280000000a则保存了两个int类型的变量(a=10,也就是0x0a,b=40,也就是0x28)。
  • 根据_vptr.A = 0x400d10 <vtable for D+16>可知,派生类的虚函数表的起始地址应该是0x400d00,通过x/4xg 0x400d00可以获得虚函数表的内存空间数据,其中,0x0000000000400d40指向派生类的typeinfo,0x0000000000400a58指向函数D::func_a()。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值