-
参考链接
-
总览
- 主要介绍对象的内存布局.
- 比如对齐,偏移,虚表,虚表在内存位置等.
- 关于一个类的信息,都在
ABI中,可以随时访问.
-
基本概念
-
sizeof(O)- 关键字表示某个对象占用字节.
- 比如
sizeof(int) == 4一样.
-
align(O)- 关键字表示某个对象的对齐是多少.
C语言中的字节对齐,比如1,2,4,8字节对齐.
-
offset(C)- 表示在对象
O中,成员变量C相对于第一个的偏移量.
- 表示在对象
-
小结
- 前面的这些信息在编译后都可以知晓.
- 在执行时也可以知晓.
- 对一个类即成员变量都有相关信息的记载.
-
dsize(O)- 也就是
sizeof(O) = dsize(O) + padding. padding即为了对齐在对应位置进行补齐.
- 也就是
-
nvsize(O)- 也就是去掉虚继承的类的大小.
virtul继承的类,包括父类用virtual继承的某个祖父类.
-
nvalign- 去掉
virtul父类后的对齐.
- 去掉
-
-
POD数据类型 -
成员指针
-
成员变量指针
int T::*varname = &T::member;- 访问就可以通过对象访问.
T().*varname; - 在
ABI中,其属性使用ptrdiff_t记录. 即某个成员在某个类的内存布局中的偏移量. - 注意区别空指针和偏移量为
0.虽然两者值都一样. 一般来说,用-1表示空指针,而不应该用NULL表示. - 但是
-1也是可能的,比如,用父类的成员指针,通过偏移量,强转之类,计算前一个父类的成员. 这种不建议,也不合适. - 强转加上偏移量虽然也可以获取. 但是不建议.
- 直接进行偏移量的加减以此访问前后的数据虽然也可以,但是也不可取.
- 注意:
virtual类型的类型转换不支持. TODO- 总结: 成员变量指针的值是偏移量,解引用则是进行加减.
-
成员函数指针
- 不同平台实现不同.
- 一般是用
struct{fnptr_t ptr;ptrdiff_t adj;},ptr表示函数位置.adj表示对象位置. ptr是虚函数,则是1+offset_in_vtable,如果是普通函数则是地址.+1是为了区分空指针.0表示空指针,1表示偏移量为0.在调用的时候加进来.adj则是表示在调用之前,需要添加对应的偏移量.指针指向对应函数的对应对象.- 影响结构体和指针实现的依据:
- 函数地址低位为0,这个很多都没有实现,这个依赖平台.
- 虚函数中,空的函数指针必须要和偏移量为
0区分. 前面介绍了+1的操作规避. - 函数在虚表中的偏移量不会是奇数. 这种也和实现有关,有的可能指针没有对齐,或者指针是奇数位.
- 虚函数调用,在仅仅知道偏移量和类型的时候也可以调用. 大多都可以,偏移加上虚表首地址定位到对应位置存放的函数指针.
- 可以进行指针的加减运算,以获取某个函数. 注意: 是否可以用于访问
protected的虚函数指针. - 执行函数调用:
adj += this,以转移到正确位置.ptr的转换,得到函数对应地址.
-
-
非
POD类类型-
简介
- 即一个类不符合
POD规定,即C++风格的类. - 下面就是介绍这类数据的内存布局.
- 即一个类不符合
-
背景
C类型的类,这个类C不符合POD for the purpose of layout的定义.- 并且,假设
C的所有的信息已经处理,即成员变量和父类的size,dsize,nvsize,alignment,nvalign都已经明确. - 那么下面就介绍如何将这些组合成一个新的,符合规范的类
C的内存布局. - 父类和成员都已经明确,但是自己还没有明确的组装好.下面就开始分析怎么组装.
-
1.Initialization- 先将
C的相关信息初始化为0. -
- 如果
C是一个多态类.
- a. 找到父类中直接或间接继承的
virtual类,从中赛选出是primary base class的类. 将这列命名为indirect primary base class,即间接的主类. - b. 如果
C有一个类是多态类,从这些类中找出一个符合条件的类B作为primary base class,即公用一个virtual table. 先从直接父类中,非virtual继承的里面找符合条件的.如果一个都不符合,找广度优先遍历找到的第一个nearly empty base class作为primary base class,同时这个类还需要满足不是indirect primary base class. 最后则从indirect primary base class中找第一个作为primary base class. - c. 如果
C还是没有找到primary base class,自己创建一个虚表,并初始化.
- 如果
- 前面
2.b描述的设计现在看来有点问题. 将第一个indirect primary base class作为C的primary base class并不会节约空间.甚至还会造成
- 先将
-
02 内存布局
最新推荐文章于 2025-09-21 11:56:12 发布
1585

被折叠的 条评论
为什么被折叠?



