iOS 内存对齐探究

影响OC对象内存大小的因素

数据类型内存大小:


占用大小.png

代码分析

@interface QHPerson : NSObject

{
    //isa 8
    NSString *level; //8
}
@property (nonatomic, copy) NSString *name; //8
@property (nonatomic, copy) NSString *nickName; //8
@property (nonatomic, assign) int age; //4
@property (nonatomic, assign) long height; //8
@end

QHPerson *p = [[QHPerson alloc] init];
p.name = @"qinhan";
p.age = 18;
size_t instansSize =  class_getInstanceSize([QHPerson class]);
NSLog(@"instansSize :%lu",instansSize);

通过class_getInstanceSize获取实例的大小,

打印结果.png

根据我上面标注的结果是44,为什么打印结果是48内,实际上在alloc的时候苹果做了8字节的对齐处理,参考上篇文章
控制变量,我们添加个方法
添加方法.png

发现内存大小不变
减少成员变量或属性
注释成员变量.png

打印结果:
打印.png

发现内存大小变小
总结:对象分配的内存大小成员变量属性有关

OC对象内存分析

内存分析.png

然后我们去掉char1这个变量
内存分析.png

  • 可以看到第三段内存的变化0x0000001200000063,第二次0x0000000000000012,两次int所占的字节不一样,由此可见底层做了字节对齐的优化处理。
  • x/8gx p 是lldb简写指令,下面附上一张别人总结的,以便理解
    LLDB文档.png

pragma pack(show)

  • pragma pack(show) 的大致作用就是改变编译器的对齐方式,如果不设置默认是8,我们也可以通过show的置来改变。
  • 最终的对齐方式还是要取变量所占的字节对比,取更小的,min(a,show). 比如int是4字节,默认是8 ,该成员就会以4字节对齐。
    截屏2021-06-09 上午10.02.27.png

内存对齐原则

数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储。这个整数应该是编译器设置的值和成员类型的值中的小值。

2.当结构体嵌套了结构体时,作为数据成员的结构体的自身长度取内部结构体的最大成员的内存大小,比如结构体a嵌套结构体bb中有charintdouble等,去最大的作为b的自身长度为,这里取double类型为8,这个8也要于编译器设置的值进行对比,如果show = 4,那么应该去4.
3.结构体的内存大小必须是结构体最大成员内存大小的整数倍,不足的需要补齐

规则验证

下面定义了两个结构体来验证一下内存的大小

struct QHStruct1{
    char a;     //1字节
    double b;   //8字节
    int c;      //4字节
    short d;    //2字节
}QHStruct1;
struct QHStruct2{
    double b;   //8字节
    int c;      //4字节
    short d;    //2字节
    char a;     //1字节
}QHStruct2;

查看打印结果

打印结果.png

纳尼,打印结果不一样,同样的成员顺序不一样打印结果居然不一样。但是如果我们了解内存对齐规则,就不会这么认为了
通过上面的对齐规则,通过图表的形式展现了,
QHStruct1和```QHStruct2``的内存分布,与打印结果一致
结构体内存分布.png

计算结构体QHStruct1 内存大小详细流程

变量a:占1个字节,从0开始,此时min(0,1),即 0存储 a
变量b:占8个字节,从1开始,此时min(1,8)1不能整除8,继续往后移动,知道min(8,8),从8开始,即8-15 存储b
变量c:占4个字节,从16开始,此时min(16,4)16可以整除4,即 16-19 存储 c
变量d:占2个字节,从20开始,此时min(20, 2)20可以整除2,即20-21 存储 d

计算结构体QHStruct2 内存大小详细流程

变量b:占8个字节,从0开始,此时min(0,8),即0-7 存储b
变量c:占4个字节,从8开始,此时min(8,4)8可以整除4,即 8-11 存储c
变量d:占2个字节,从12开始,此时min(12, 2)12可以整除2,即12-13存储 d
变量a:占1个字节,从14开始,此时min(14,1),即 14存储a

结构体嵌套
struct QHStruct2{
    double b;   //8字节
    int c;      //4字节
    short d;    //2字节
    char a;     //1字节
}QHStruct2;

struct QHstruct3{
    double b;   //8字节 0-7
    int c;      //4字节 8 9 10 11
    short d;    //2字节 12 13
    char a;     //1字节 14
    struct QHStruct2 str; //
    
}QHstruct3;

其实嵌套后和没有嵌套逻辑一样,只不过这里的str要按照成员里面最大的字节8来计算,相当于n =8, 这样就很容易算出,结构体从16出开始放,这样就是16+16=32字节

计算内存大小的几个方法

class_getInstanceSize
sizeof
malloc_size
举个例子

- (void)test1
{
    QHPerson *p = [[QHPerson alloc] init];
    
    p.name = @"qinhan";
    p.age = 18;
    p.nickName = @"123";
    //p.height = 180;
    p->level = @"青铜";
   // p.char1 = 'c';
    
    size_t instansSize =  class_getInstanceSize([QHPerson class]);
    NSLog(@"sizeOf :%lu",sizeof(p));
    NSLog(@"instansSize :%lu",instansSize);
    NSLog(@"objc对象实际分配的内存大小:%lu",malloc_size((__bridge const void*)(p)));
}

打印结果


截屏2021-06-08 下午6.36.07.png

发现instansSize 计算的大小和malloc_size计算大小不一样,
这是因为instansSize8字节对齐,也就是是8的倍数
imalloc_size16字节对齐,也就是16的倍数

内存优化

通过上面结构体内存对齐以及上面的内存分析,发现属性的顺序不一样,内存大小不一样,所以苹果底层做了一些优化.用空间换时间,将类中的属性进行重排,以此来达到内存优化的目的

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容