OC底层(一) NSObject对象本质

在我们平时写的Objective-C代码,底层实现的其实都是C\C++代码,编译过后会转换成C\C++代码,最后又会转成汇编语言,然后是机器码
image.png
    先在main.m定义了一个继承于NSObject的类 然后通过命令行 xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m 获得生成的C\C++代码 打开生成后的main.cpp可以看到
OC底层(一) NSObject对象本质_第1张图片
image.png
OC底层(一) NSObject对象本质_第2张图片
image.png
image.png
OC底层(一) NSObject对象本质_第3张图片
image.png

IMPL的意思就是implementation实现的意思上图可以看的比较清楚在OC的头文件里面NSObject底层实现就是左边里面只有一个成员变量isa,在底层实现里面NSObject本质他就是一个结构体(图的右边)。Class点进去看就是一个指向结构体的指针,在64位环境下占8个字节,所以NSObject在内存中就占8个字节,但是真正的的情况是占16个字节,通过运行时runtime可以发现,且看下面分析。

OC底层(一) NSObject对象本质_第4张图片
image.png
image.png
由上图不难看出NSObject实例对象的成员变量所占用的内存大小是8个字节,实例对象obj获得系统分配的内存是16个字节,所以NSObject占用的内存大小就是系统分配的内存大小16字节。runtime部分源码是开源的,上面class_getInstanceSize可以通过源码( 源码下载网站)(后缀数字越大代表源码最新)可以看出
OC底层(一) NSObject对象本质_第5张图片
image.png
OC底层(一) NSObject对象本质_第6张图片
image.png
image.png

是通过一个instanceSize的方法返回最后的大小,而instanceSize方法里面写的最低返回就是16个字节,硬性规定了最少16个字节。如果是NSObject的话通过size_t size = alignedInstanceSize() + extraBytes;拿出来的是8个字节。方法alignedInstanceSize返回的是成员变量大小,extraBytes额外的一般来说是0字节。

从另一个角度去看,首先我们打个断点,查看obj的内存地址,然后选择Debug->Debug Workflow->View Memory 在下图框中输入断点查看的地址敲回车
OC底层(一) NSObject对象本质_第7张图片
image.png
OC底层(一) NSObject对象本质_第8张图片
image.png
OC底层(一) NSObject对象本质_第9张图片
image.png

刚才我们通过源码了解到系统为obj分配了16个字节,上图绿色框框中框出了16个字节,1个16进制位代表4个2进制位,2个16进制位就代表8个2进制位,也就是1个字节。前8个字节就代表isa,后面8个字节都是00,再后面就不是0,所以能推断出这16个字节是连续的,红色框框框的就是其它的内存,最严谨的方法还是通过运行时获取。

    最后总结一下就是:
    1.一个NSObject对象占用多少内存?
    系统分配了16个字节给NSObject对象(通过malloc_size函数获得)
    但NSObject对象内部只使用了8个字节的空间(64bit环境下,可以通过class_getInstanceSize函数获得)

    创建一个实例对象,至少需要多少内存?
    #import 
    class_getInstanceSize([NSObject class]);

    创建一个实例对象,实际上分配了多少内存?
    #import 
    malloc_size((__bridge const void *)obj);

有兴趣的可以自己新建一些复杂的继承NSObject的对象看看内存再根据源码自己验证分析一下

这里附上常用LLDB指令,也可以通过一些指令读取内存,有疑问请联系博主,有些图片非原创!
OC底层(一) NSObject对象本质_第10张图片
image.png

你可能感兴趣的:(OC底层(一) NSObject对象本质)