美文网首页程序员
一个NSObject对象占用多少内存?

一个NSObject对象占用多少内存?

作者: 三线小奋青 | 来源:发表于2018-09-11 16:20 被阅读40次

    今天来聊聊NSObject对象占用多少内存的话题。

    一.什么是NSObject对象?

    NSObject *obj = [[NSObject alloc] init];这句代码中,obj是对象么?NONONO……很多人有这个误解,认为这个obj就是对象。正解:[[NSObject alloc] init]这个才是对象,obj是个指针,也就是obj指针指向的那片内存空间叫做对象。

    二.对象本质是什么?

    OC的底层是C和C++来实现的,那么可以猜测一下,这样一个复杂的的可以包含各种数据类型的集合,所对应的C的数据结构是什么呢?数组?字典?集合?结构体?
    我们不烦大胆猜测一下……思索过后发现只有结构体大体符合,那么咱们来验证一下。
    将含有下面的代码的main.m转成C++文件(main.cpp)
    (定位到main.m,在终端输入指令xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp)

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            NSObject *obj = [[NSObject alloc] init];
        }
        return 0;
    }
    

    在main.cpp文件中发现了这样的一个结构体:

    struct NSObject_IMPL {
        Class isa;
    };
    

    看见isa指针,就觉得好亲切。这说明了两个问题:

    • 每个对象的底层都是一个结构体
    • 每个对象内部都有一个isa指针

    那么问题来了,64位下指针占用8个字节,那是不是一个对象占用8个字节的内存空间呢?答案显然不是。因为还有我们的成员变量啊,所以到此为止,得出结论:一个对象至少需要占用8个字节的内存空间来存放isa指针

    此处介绍两个计算内存空间大小的方法:

    • runtime 中的class_getInstanceSize()
      *(return The size in bytes of instances of the class,返回一个类的实例对象的大小,其实就是底层结构体的大小)
    • malloc_size()
      (获得对象所开辟空间的大小)
      image.png
      由上图可以看出,结构体大小为8个字节,但是系统给它分配了16个字节。

    三.自定义一个继承于NSObject的类,研究实例对象的内存空间

    1.场景一

    @interface Dog :NSObject{
        @public
        int _age;
        int _height;
    }
    @end
    

    新建一个Dog类继承于NSObject,按上述操作转化成c++代码。得到:

    struct Dog_IMPL {
        struct NSObject_IMPL NSObject_IVARS;
        int _age;
        int _height;
    };
    

    猜测:struct NSObject_IMPL 结构体里边只有一个isa指针,占用8个字节。int类型在64位下,占用4个字节。那么这个Dog对象占用8+4+4=16个字节。
    提醒:在计算的时候要注意一个问题:结构体的内存对齐

    我们分别用class_getInstanceSize()和malloc_size()方法验证一下。


    场景一测试

    2.场景二

    给Dog类在添加一个int成员变量,如下

    @interface Dog :NSObject{
        @public
        int _age;
        int _height;
        int _weight;
    }
    

    猜测:struct NSObject_IMPL 结构体里边只有一个isa指针,占用8个字节。int类型在64位下,占用4个字节。根据内存对齐原则,那么这个Dog对象占用8+4+4+8=24个字节。

    继续用上述方法,测试内存,如下


    场景二测试

    疑问:为什么会出现32呢?
    解答:根据上边对两个计算内存方法的解释:
    class_getInstanceSize():说白了就是计算结构体所占内存的大小;
    malloc_size():计算对象所开辟的内存空间的大小;
    一个是理论计算,一个是实际大小。为什么会出现这样的差距呢?这就是系统框架的限制。此处不做深入研究。

    四.方法的内存都跑到哪里去了?

    对于这个东西,请大家看我的另一篇对于oc方法的论述。现在只需要知道,一个实例(instance)对象中不存储方法。
    传送门:

    五.总结

    结论:
    1.一个NSObject对象,系统分配了16个字节的空间,但是实际上用了8个字节的空间
    2.一个实例对象的内存空间=它的底层结构体的内存大小+系统框架给的限定
    3.实例对象的内存中不包括方法的内存

    相关文章

      网友评论

        本文标题:一个NSObject对象占用多少内存?

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