OC对象分配内存的底层原理

1、 OC代码编译过程


OC对象分配内存的底层原理_第1张图片
编译过程

从图可看出

1、Objective-C代码,底层实现其实都是C\C++代码

2、Objective-C的类都是基于C\C++的数据结构实现的。

2、Main文件写的源码如下


OC对象分配内存的底层原理_第2张图片

•在Main文件里面新建了HPStudent类,HPPerson类。HPStudent继承HPPerson.

•在编译生成的cpp文件中看下我们的类到底变成什么样子了?

•Objective-C代码转换为C\C++代码,然后看下OC类到底变成啥样子。

•命令:xcrun  -sdk  iphoneos  clang  -arch  arm64  -rewrite-objc OC源文件 -o 输出的CPP文件


OC对象分配内存的底层原理_第3张图片

3、查看cpp文件源码, HPStudent类的结构 


OC对象分配内存的底层原理_第4张图片

里面有一个结构体structHPPerson_IMPL变量NSObject_IVARS,还有成员变量_no

4、HPPerson类结构


OC对象分配内存的底层原理_第5张图片

5、 NSObject类结构 


OC对象分配内存的底层原理_第6张图片

6、 获取内存分配大小的函数 

•1、运算符:sizeof(obj) ,运算obj指针需要的内存大小

•2、class_getInstanceSize(class)获取某个类需要的内存大小。需要导入#import

•3、malloc_size(const void *ptr);获取某个指针指向的内存空间实际分配的内存大小。

需要导入:import

7、HPStudent对象内存分配情况


OC对象分配内存的底层原理_第7张图片
OC对象分配内存的底层原理_第8张图片

为啥不一样?

•1、sizeof(obj) 运算得到的是obj指针的内存大小,在64位的机器中(比如MAC or iphone),指针的内存大小是8字节。所以打印出8。

•2、class_getInstanceSize得到的是HPStudent实例对象需要的内存大小。那为什么不是8字节指针+int型_no的4字节+_age4字节+_height4字节=20个字节呢?而是24字节?

       因为结构体存储尊享内存对齐规则,结构体的对齐值是成员变量内存最大值(默认情况,也可以通过#pragma pack(value)指定其他值)。在Student这个结构体中isa指针占用8字节是最大值,作为对齐值来计算结构体需要的内存大小,也就是8+8+8=24字节。

•3、如果HPPserson的成员变量改成@private。class_getInstanceSize获取的内存大小为啥还是24字节?

        改成私有变量也是属于结构体的一部分,从上面Student结构体看出,里面有个Person结构体成员,不管Person结构体内成员变量是什么权限,都需要分配固定内存给   这个结构体也就是Person结构体大小没变化。所以Student的大小也是不变,还是24。

•4、malloc_size获取得到的内存大小为啥是32字节,而不是24呢?

1)mallco_size获取的是对象实际占用的内存大小。那么对象的实例化过程中,核心是调用allocWithZone。这个方法是属于objc库里面的


OC对象分配内存的底层原理_第9张图片

objc库是开源的:http://opensource.apple.com/tarballs/objc4/

下载后找到NSObject的allocWithZone调用核心是:


OC对象分配内存的底层原理_第10张图片
OC对象分配内存的底层原理_第11张图片


OC对象分配内存的底层原理_第12张图片

里面的核心是调用了calloc\mallco_zone_calloc函数,由于是默认没有指定size内存大小,此处是size=0.

这个底层函数,可以下载源码查看(https://opensource.apple.com/tarballs/libmalloc/)

 里面很多calloc分配内存函数,很乱。找资料后面找到NANO_MAX_SIZE这个宏定义。是作为分配内存大小的一个值。

OC对象分配内存的底层原理_第13张图片

        从这个值可以知道,我们手机ios或者mac os系统里面的分配内存是按16的倍数来分配内存大小的。系统分配内存也是遵循内存对齐的规则(提高存储效率),系统相当于把内存按16的倍数切格好一块块的小内存,我们的Student需要的内存是24字节,刚刚好可以分一块32自己的内存给Student的对象。因此Student对象最终分配的内存大小是32。

你可能感兴趣的:(OC对象分配内存的底层原理)