美文网首页iOSIT干货
iOS底层原理之一:一个NSObject对象占多大内存

iOS底层原理之一:一个NSObject对象占多大内存

作者: 估唔到 | 来源:发表于2018-09-01 01:21 被阅读171次

    题记

    这系列的目的是回顾一下学到的知识,对OC底层原理作一翻探究,以及对一些常见的底层原理面试题作一次总结。

    准备工作


    • 如题目所示,我们新建一个demo来探究:一个NSObject对象占多大内存


    如大部分iOS开发者所知,OC的底层是C/C++,为了清楚了解NSObject的本质,我们可以看看底层是怎么实现。

    • 进入mian.m文件所在的路径,打开terminal
    • 输入以下指令把OC代码转成C++(因为mac平台下使用的是arm64架构,实际情况可以选择相应的架构)
    xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp 
    
    • 我们可以得到一个main-arm64.cpp 文件


    • 把cpp文件直接拽入Xcode,为了不显示报错信息,我们不让它参与编译


    探究


    • 点击NSObject我们可以看到OC的定义


    • 在main.cpp文件里面搜索NSObject_IMPL,我们可以看到NSObject转成C++后的本质是一个结构体


    • 我们再点击Class进去,可以看到其实它就是一个指针。那么我们知道在64位环境下,它占8个字节。


    论证


    • 有了这个推论,我们还可以进一步论证我们的观点,这里我们用到runtime,也就是运行时的一个方法class_getInstanceSize
    • 为了验证推论的准确性,我们先找到苹果开源的源码,打开浏览器http://opensource.apple.com/tarballs/搜索`objc
    • 点击进去,我们找到数字最大的一个,一般来说也是最新的一个


    • 下载压缩包解压后并打开


    • 搜索class_getInstanceSize,并在.mm文件里面可以看到它的实现
    • 点击3中的alignedInstanceSize()方法,我们可以看到进一步注释,这个方法返回的是类对象成员变量所占用的内存大小


    • 所以通过调用runtime的这个方法我们可以看到,NSObject类对象所占用的内存大小为8个字节


    疑问


    • 这个就是最终结果了吗?不用急着下定义。我们还有个叫malloc_size的方法可以查看系统分配内存的大小。由于这里需要传一个C的指针,所以我们打印obj的时候需要桥接一下。然后我们会发现,返回的大小是16而不是8!


    总结


    • 为什么会造成这个不一致呢?我们还是要从源码入手分析,首先还是在objc的源码里面搜索allocWithZone这个方法,查看创建一个对象是内存是怎么分配


    • 我们点击进入class_createInstance这个方法,看到返回的是_class_createInstanceFromZone方法,我们再次点击进去就能很快锁定我们需要的信息:size
    • 我们可以从注释看到,所有对象至少分配16 bytes 的大小,从方法实现来看,如果size < 16,则size = 16



    所以我们可以很好的回答这个问题,系统分配了16个字节空间给NSObject对象,但是在64位环境下,NSObject只使用了8个字节。

    相关文章

      网友评论

        本文标题:iOS底层原理之一:一个NSObject对象占多大内存

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