上篇文章简单的了解了一下iOS结构体的内存分配,而OC对象的本质就是结构体。由此我们可以探究一下OC对象的内存布局方式。
在探究过程中使用到的一些命令行
- x p 此命令用于打印对象的内存地址分配情况,但打印出来的内容很难阅读,所以可以使用下个命令进行优化
- x/ngx p 以16进制打印对象p内存地址,打印n段
- sizeof(p) 获取p对象的内存大小
- class_getInstanceSize([P class]) 获取类对象分配的大小,需要引入运行时库
- malloc_size((__bridge const void *)(p)) 获取p对象在系统成面上分配的内存的大小
探究对象内存分配
以下是内存打印状况创建一个类Person,属性定义如下:
@property(nonatomic, copy)NSString *name;
@property(nonatomic, copy)NSString *age;
@property(nonatomic, assign)int hight;
@property(nonatomic, assign)int sex;
@property(nonatomic, assign)double x;
对象内部的内存地址分配方式打印分析:
- person是一个指针类型,在OC中指针的大小为8字节,所以sizeof(person)输出为8字节
- Person是一个类,本质是个结构体,经过分析可得出内存占用是32字节。但实际打印是40,原因是OC对象本身有一个isa指针,该指针占用了8字节。ps:这也是为什么我们打印数组的首地址不是第一个元素地址的原因
- Person类本身的内存占用是按照最大8字节对齐,所以为40位。但苹果当前的内存分配是16位对齐,所以其在内存开辟时实际开辟的大小由于对齐方式的原因最终开辟出的大小为48位
在随意一处打印断点,在命令行使用x p命令可以获取对象内存分配方式,这种方式获取的内存分配很难读懂,所以可以作为了解
使用x/nxg p 命令可以按照每段8位的16进制形式打印内存。由于Person类本身占用内存为48字节,所以使用x/6xg 打印出所有内存的分配方式
数据意义分析
- 每行的第一个地址如0x600003b80600代表着该段内存空间在内存中的地址,由于系统按照16位对齐,所以看到三段内存地址是顺序递增的
- 由于OC对象默认有一个isa的指针,所以打印第一个地址为Peron对象本身
- 按照结构体内存分配原则理论上我们打印0x00000001000000b9位置的内存该输出属性的name,但实际会打印出一串数字。原因在于属性中有两个int类型,内存大小为4字节,为了保证可读性苹果对齐进行了优化,所以这两个属性是以16进制存放在0x00000001000000b9这个内存地址。另外对于数值类型苹果也会对其进行优化,所以可以通过内存空间地址直接获取对应的值
- 可以看到最后一个内存地址为0x000000000000000,对其进行打印发现最终输出为nill。这也说明了Person类本身占用的地址空间为40字节,但系统实际开辟的内存空间为48位,遵循16进制对齐的原则
以上就是此次对于OC对象内存空间分配的探究过程,如有错误欢迎评价指正哦~