美文网首页
iOS结构体内存计算和对齐

iOS结构体内存计算和对齐

作者: 学到不懂为止 | 来源:发表于2020-09-09 16:40 被阅读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打印调试,如图


lldb打印分析.png

打印日志结果可以分析出几点:

  • nickNameage1age2属性不赋予值,内存情况会出现0x0000000000000000;
  • ageheight属性会出现在同一个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的结果,必须是其内部最大成员的整数倍,不足的要补齐

类型对应的占用字节大小图:


类型占用字节大小图.png

上面几点估计理解起来比较困难,那么我举简单的例子:

struct LNDStruct1 {
    double a; //占用8字节
    char b; //占用1字节
    int c; //占用4字节
    short d; //占用2字节
};

如图示意


LNDStruct1内存分布.png

计算步骤为:

  • LNDStruct1结构体中最大属性占用8字节;
  • a属性从第[0 7]字节之间存储,理论上下一个属性从第8字节开始存储;
  • 先判断属性b占用1个字节,81的整数倍,所以第8个字节储存b,理论上下一个属性从第9字节开始存储;
  • 先判断属性c占用4个字节,9不是4的整数倍,依次往下推算第1011字节都不是,第12个字节是,所以第12个字节开始储存属性c,属性c占用字节空间为[12 15],理论上下一个属性从第16字节开始存储;
  • 先判断属性d占用2个字节,162的整数倍,所以第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个字节
};

如图示意


LNDStruct2内存分布.png

计算步骤为

  • LNDStruct2结构体中最大属性占用8字节;
  • 根据上面例子的步骤可知属性e占用字节空间[0 7]f占用字节空间[8]g占用字节空间[12 15]h占用字节空间为[16 17],理论上下一个属性从第18字节开始存储;
  • 接下来计算st结构体中属性了
    • 先判断属性a占用8个字节,18不是8的整数倍,依次往下推算第1920212223字节都不是,第24个字节是,所以第24个字节开始储存属性a,属性a占用字节空间为[24 31],理论上下一个属性从第32字节开始存储;
    • 先判断属性b占用1个字节,321的整数倍,所以第32个字节开始储存属性b,属性b占用字节空间为第32,理论上下一个属性从第33字节开始存储;
    • 先判断属性c占用4个字节,33不是4的整数倍,依次往下推算第3435字节都不是,第36个字节是,所以第36个字节开始储存属性c,属性c占用字节空间为[36 39],理论上下一个属性从第40字节开始存储;
    • 先判断属性d占用2个字节,402的整数倍,所以第40个字节开始储存属性d,属性d占用字节空间为[40 41]
  • LNDStruct2结构体中所有属性相加为42个字节空间,(根据原则第3点)所以LNDStruct2结构体占用字节为48

相关文章

  • iOS-内存对齐

    先上个图,待会计算内存时会用到。 hxdm,已知iOS对象的本质是结构体,所以探索内存对齐当然是从结构体开始啦。来...

  • iOS 结构体内存对齐浅析

    什么是内存对齐 内存对齐是一种在计算机内存中排列数据、访问数据的一种方式。它包含基本数据对齐和结构体数据对齐 。 ...

  • iOS原理探索02-- 内存对齐

    结构体内存对齐 我们首先定义两个结构体,分别计算他们的内存大小,并讨论内存对齐原理 从两个结构体来看两者没啥大的区...

  • ndk-基础知识

    数组和指针,数组指针,指针数组 结构体 内存对齐 内存对齐 结构体大小 S5DUD10BN083MHEJEX7TP...

  • C 结构体对齐

    转载 结构体对齐详解 结构体数据成员对齐的意义 许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会...

  • iOS结构体内存计算和对齐

    了解一下lldb调试指令 接下来引入一个列子,创建一个LNDPersonal类 lldb打印调试,如图 打印日志结...

  • 结构体

    1.结构体 2.结构体的内存对齐模式 编译器在编译一个结构的时候采用内存对齐模式,结构体总是以最大的成员最为对齐单...

  • iOS 内存对齐:结构体继承和结构体作为另一个结构体成员变量情况

    内存对齐规则就不赘述了,这里讨论下继承和结构体作为另一个结构体成员变量的情况下,结构体内如何进行内存对齐。以下测试...

  • 内存对齐详解

    1、什么是内存对齐假设我们声明两个变量: 2、结构体内存对齐规则 结构体所占用的内存与其成员在结构体中的声明顺序有...

  • iOS 开发 内存对齐(练习)

    目录 内存对齐规则 对齐系数 面试题演练 一、内存对齐规则 (关于面试题中结构体内存对齐计算总结) 1.1、数据成...

网友评论

      本文标题:iOS结构体内存计算和对齐

      本文链接:https://www.haomeiwen.com/subject/ryprektx.html