美文网首页
OC底层(一) NSObject对象本质

OC底层(一) NSObject对象本质

作者: 搬砖小工 | 来源:发表于2018-10-24 14:01 被阅读45次
在我们平时写的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可以看到
image.png image.png image.png image.png

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

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

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

从另一个角度去看,首先我们打个断点,查看obj的内存地址,然后选择Debug->Debug Workflow->View Memory 在下图框中输入断点查看的地址敲回车 image.png image.png 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 <objc/runtime.h>
    class_getInstanceSize([NSObject class]);

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

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

这里附上常用LLDB指令,也可以通过一些指令读取内存,有疑问请联系博主,有些图片非原创! image.png

相关文章

网友评论

      本文标题:OC底层(一) NSObject对象本质

      本文链接:https://www.haomeiwen.com/subject/gacttqtx.html