iOS OC 对象原理探索二
2020-04-20 15:02
961 查看
iOS OC 对象原理探索二
上一篇提到alloc开辟内存是8字节对齐,用空间换取查找时间,那么像
int、char这样非8字节的变量,在内存中是什么样的呢?
首先我们看看对齐原则如下:
内存对齐原则
1. 数据成员对齐规则:
结构体(struct)或(联合体union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的 起始位置要从该成员大小或者成员的子成员大小的整数倍开始(只有该成员有子成员,比如数组、结构体等), 例如:int为4字节,则要从4的整数倍地址开始存储
2. 结构体作为成员:
如果一个结构体里有某些结构体成员,则结构体成员要从其中内部最大元素大小的整数倍地址开始存储. 例:(struct a 中存有 struct b, b中有char,int,double等元素,那么b应该从8的整数倍开始存储)
3. 收尾工作:
结构体的总大小,也就是sizeof的结构,必须是起内部最大的成员整数倍,不足的要补齐
接下来看一下在
结构体和
结构体嵌套中每个变量所占内存的分析,分析代码如下:
struct LGStruct1 { char a; // 1 + 7 min(0 1) 0 double b; // 8 min(1 8) (1-7填充) 8 9 10 11 12 13 14 15 short d; // 2 + 2 min(16 2) 16 17 int c; // 4 min(18 4) (18 19填充) 20 21 22 23 -- 24 } MyStruct1; struct LGStruct2 { double b; // 8 0-7 int c; // 4 min(8 4) 8 9 10 11 char a; // 1 min(12 1) 12 short d; // 2 min(13 2) (13填充) 14 15 -- 16 struct LGStruct1 r; // min(16 24) struct里最大double 8的倍数 } MyStruct2; // struct里最大double 8,从8的倍数地址开始存储 // NSLog(@"%lu-%lu",sizeof(MyStruct1),sizeof(MyStruct2)); // 输出 24-40 struct LGStruct3 { double b; // 8 0-7 int c; // 4 min(8 4) 8 9 10 11 char a; // 1 min(12 1) 12 struct LGStruct1 r; // min(13 24) (13 14 15) // 16 - 39 struct里最大double 8的倍数 short d; // 2 min(40 2) 40 41 -- 48 } MyStruct3; // struct里最大double 8 补齐为48 // 结构体的总大小,也就是sizeof的结构,必须是起内部最大的成员整数倍,不足的要补齐// 输出 24-48
根据上面代码打印分析,我们很容易分析出
结构体struct和
结构体struct嵌套所占的内存,完全遵守内存对齐原则。
成员变量内存探究
上一篇文章我们分析alloc源码得知,对象开辟内存空间是8的倍数(8字节对齐),最少占用16字节(16 - 8 > 16),那么系统真的会按照我们的意愿开辟内存么?下面我们来分析一下:
1.代码分析
LGTeacher *p = [[LGTeacher alloc] init]; p.name = @"Cooci"; p.age = 18; p.height = 185; p.hobby = @"女"; p.sex = 2; p.ch1 = 'a'; p.ch2 = 'b';
打印分析如下:
由此可以看出,对象的属性并未按照每个属性8字节来开辟内存的,而是按照开篇所说的内存对齐原则来分配的,那么我们分析一下代码:
LGTeacher *p = [LGTeacher alloc]; // isa ---- 8 p.name = @"LG_Cooci"; // 8 p.age = 18; // 4 p.height = 185; // 8 p.hobby = @"女"; // 8 NSLog(@"%lu - %lu",class_getInstanceSize([p class]),malloc_size((__bridge const void *)(p)));
应该占40个字节,那么实际系统开辟的内存打印如下:
实际开辟了48内存,对象申请的内存的大小 和 系统开辟的大小并 不一致,接下来我们分析一下
calloc源码分析,看一下系统是怎么开辟内存的
2.calloc源码分析
通过源码分析,流程如下:
关键代码:
static MALLOC_INLINE size_t segregated_size_to_fit(nanozone_t *nanozone, size_t size, size_t *pKey) { // size = 40 size_t k, slot_bytes; if (0 == size) { size = NANO_REGIME_QUANTA_SIZE; // Historical behavior } // 40 + 16-1 >> 4 << 4 // 40 - 16*3 = 48 // // 16 k = (size + NANO_REGIME_QUANTA_SIZE - 1) >> SHIFT_NANO_QUANTUM; // round up and shift for number of quanta slot_bytes = k << SHIFT_NANO_QUANTUM; // multiply by power of two quanta size *pKey = k - 1; // Zero-based! return slot_bytes; }
由此看出:
对象开辟内存是16字节对齐,是参照整个当前对象;前面8字节对齐,是参照对象里面的属性。 16字节对齐,系统开辟内存,避免风险,防止内存溢出,属性8字节内存对齐也有一定多余的空间 不确定属性具体排列顺序,不确定末尾是否有
- 点赞
- 收藏
- 分享
- 文章举报
相关文章推荐
- iOS OC 对象原理探索三
- 深入理解javascript内部原理(2): 变量对象(Variable object)
- 利用js的闭包原理做对象封装及调用
- 学习Scala:伴生对象的实现原理
- python学习之列表对象实现原理解析
- 探索C++对象模型之 多重继承与虚函数表
- JSP--JSP简介及原理;3个指令;6个动作;9个对象
- [转]详叙 Serializable "对象序列化"的用法和原理
- 番外 01:Spring IoC 实现原理简析,Java的反射机制,通过类名创建对象
- 面向对象分析设计学习与探索(二):好的应用程序设计(Well-designed apps rock)
- Inside The C++ Object Model (深度探索C++对象模型) 第一讲 关于对象
- 深度探索C++ 对象模型【第一章3】
- cocos2d-x 将cocosbuilder输出文件映射成对象的原理
- 《深度探索c++ 对象模型》有感之默认构造函数,拷贝构造函数,拷贝运算符的合成
- 使用临界段实现优化的进程间同步对象-原理和实现
- ajax原理和XmlHttpRequest对象
- PHP5.0对象模型探索之抽象方法和抽象类
- 数据标准化与PCA白化原理探索
- Ruby原理剖析-- 对象与类的内部数据结构
- 模块分解原理的探索