iOS结构体内存计算和对齐
2020-09-09 本文已影响0人
学到不懂为止
了解一下lldb
调试指令
po 打印信息
p 打印详细的信息
bt 打出堆
register read 读取寄存器
x 读取内存段
x/4gx 读取4段内存段
接下来引入一个列子,创建一个LNDPersonal
类
@interface LNDPersonal : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic, assign) int age1;
@property (nonatomic, assign) int age2;
@property (nonatomic, assign) int age;
@property (nonatomic, assign) int height;
@end
lldb打印调试,如图
![](https://img.haomeiwen.com/i4050259/87475d8f30b2cbf6.png)
打印日志结果可以分析出几点:
-
nickName
、age1
、age2
属性不赋予值,内存情况会出现0x0000000000000000; -
age
、height
属性会出现在同一个8字节里; - 属性在内存中排列乱了;
总结:类本身其实就是一个结构体,默认有一个isa
属性占用8字节,苹果对对象的申请内存空间默认16字节整数倍算,但实际开辟是以8字节整数倍算。为了能够较快速访问、避免访问不出错,则使用了内存字节对齐
方式优化。
内存字节对齐原则
1、数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int为4字节,则要从4的整数倍地址开始存
储。 min(当前开始的位置mn)m=9n=4 9 10 11 12
2、数据成员为结构体:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)
3、结构体的整体对齐规则:结构体的总大小,即sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐
类型对应的占用字节大小图:
![](https://img.haomeiwen.com/i4050259/3601a2ef427dbeea.png)
上面几点估计理解起来比较困难,那么我举简单的例子:
struct LNDStruct1 {
double a; //占用8字节
char b; //占用1字节
int c; //占用4字节
short d; //占用2字节
};
如图示意
![](https://img.haomeiwen.com/i4050259/bc172f11f0dc41a4.png)
计算步骤为:
-
LNDStruct1
结构体中最大属性占用8字节; -
a
属性从第[0 7]
字节之间存储,理论上下一个属性从第8
字节开始存储; - 先判断属性
b
占用1个字节,8
是1
的整数倍,所以第8
个字节储存b,理论上下一个属性从第9
字节开始存储; - 先判断属性
c
占用4个字节,9
不是4
的整数倍,依次往下推算第10
、11
字节都不是,第12
个字节是,所以第12
个字节开始储存属性c
,属性c
占用字节空间为[12 15]
,理论上下一个属性从第16
字节开始存储; - 先判断属性
d
占用2个字节,16
是2
的整数倍,所以第16
个字节开始储存属性d
,属性d
占用字节空间为[16 17]
; -
LNDStruct1
结构体中所有属性相加为18
个字节空间,根据对齐原则推算出(根据原则第3点)
,所以LNDStruct1
结构体占用字节为24
。
接下来我们在上面代码上改变一下,使用结构体嵌套结构体来计算一下
struct LNDStruct2 {
double e; //占用8字节
char f; //占用1字节
int g; //占用4字节
short h; //占用2字节
struct LNDStruct1 st; //占用24个字节
};
如图示意
![](https://img.haomeiwen.com/i4050259/f3862238ceb31cd0.png)
计算步骤为
-
LNDStruct2
结构体中最大属性占用8
字节; - 根据上面例子的步骤可知属性
e
占用字节空间[0 7]
、f
占用字节空间[8]
、g
占用字节空间[12 15]
、h
占用字节空间为[16 17]
,理论上下一个属性从第18
字节开始存储; - 接下来计算
st
结构体中属性了- 先判断属性
a
占用8个字节,18
不是8
的整数倍,依次往下推算第19
、20
、21
、22
、23
字节都不是,第24
个字节是,所以第24
个字节开始储存属性a
,属性a
占用字节空间为[24 31]
,理论上下一个属性从第32
字节开始存储; - 先判断属性
b
占用1个字节,32
是1
的整数倍,所以第32
个字节开始储存属性b
,属性b
占用字节空间为第32
,理论上下一个属性从第33
字节开始存储; - 先判断属性
c
占用4个字节,33
不是4
的整数倍,依次往下推算第34
、35
字节都不是,第36
个字节是,所以第36
个字节开始储存属性c
,属性c
占用字节空间为[36 39]
,理论上下一个属性从第40
字节开始存储; - 先判断属性
d
占用2个字节,40
是2
的整数倍,所以第40
个字节开始储存属性d
,属性d
占用字节空间为[40 41]
。
- 先判断属性
-
LNDStruct2
结构体中所有属性相加为42
个字节空间,(根据原则第3点)
所以LNDStruct2
结构体占用字节为48
。