NSObject内存占用

#####1.测试用到的代码

#import <Foundation/Foundation.h>
#import <objc/runtime.h>
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSObject *obj = [[NSObject alloc] init];
        NSLog(@"%zu",class_getInstanceSize([NSObject class]));
        NSLog(@"%zu",malloc_size((__bridge const void *)obj));
    }
    return 0;
}
//打印结果为8   16

#####2.OC转化成C/C++的实质

  • clang -rewrite-objc main.m -o main.cpp将oc转成c++的代码
  • main.cpp全局搜索NSObject,会找到如下图的一段代码
    NSObject转化成C的结构.png
  • 通过上图的代码结构可以发现NSObject转化成C++的代码结构后只有一个Class isa的这么一个指针参数。
    #####内存占用的分析
    最开始的代码打印的结果分别是816。具体来分析一下这两个结果是怎么出现的。
  • class_getInstanceSize结果为8的具体实现:
    首先去找一下objc的具体底层的实现,去objc官网地址下载最新的版本。全局搜索class_getInstanceSize方法会找到如下的代码。
size_t class_getInstanceSize(Class cls)
{
    if (!cls) return 0;
    return cls->alignedInstanceSize();
}
->然后跳转到"alignedInstanceSize()"方法的实现,代码如下
// Class's ivar size rounded up to a pointer-size boundary.
"这里有一行注释,说的是返回的是成员变量的内存大小"
    uint32_t alignedInstanceSize() const {
        return word_align(unalignedInstanceSize());
    }

通过查看底层的实现结合NSObejct转化成C++的代码可以很清楚的明白为何返回内存结果为8

  • malloc_size结果为16的具体原因
    首先学过C语言的都知道malloc方法是分配内存空间的操作。而[[NSObject alloc] init]就是做初始化操作,所以其中肯定存在分配内存空间的操作。所以我们找一下alloc的具体实现。
+ (id)alloc {
    return _objc_rootAlloc(self);
}
-> "_objc_rootAlloc()"方法的实现:

_objc_rootAlloc(Class cls)
{
    return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}
-> "callAlloc"的具体实现
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
#if __OBJC2__
    if (slowpath(checkNil && !cls)) return nil;
    if (fastpath(!cls->ISA()->hasCustomAWZ())) {
        return _objc_rootAllocWithZone(cls, nil);
    }
#endif
}

-> "在'callAlloc'方法中发现最终调用的是'_objc_rootAllocWithZone '方法,
然后再来查看一下"

_objc_rootAllocWithZone(Class cls, malloc_zone_t *zone __unused)
{
    // allocWithZone under __OBJC2__ ignores the zone parameter
    return _class_createInstanceFromZone(cls, 0, nil,
                                         OBJECT_CONSTRUCT_CALL_BADALLOC);
}

-> "然后查看 '_class_createInstanceFromZone' 这个方法的实现"

_class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone)
{
    void *bytes;
    size_t size;

    // Can't create something for nothing
    if (!cls) return nil;

    // Allocate and initialize
    size = cls->alignedInstanceSize() + extraBytes;

    // CF requires all objects be at least 16 bytes.
    if (size < 16) size = 16;

    if (zone) {
        bytes = malloc_zone_calloc((malloc_zone_t *)zone, 1, size);
    } else {
        bytes = calloc(1, size);
    }

    return objc_constructInstance(cls, bytes);
}

最后在方法_class_createInstanceFromZone()方法中看到这么一行代码if (size < 16) size = 16;NSObject只有一个参数Class isa占用8个字节,小于16个字节,所以返回结果是16

#####特别说明一下
在查询源码的时候发现好多的代码分新版和旧版,有可能在新版中查询不到想要的信息,此时需要去查询旧版的信息才可能查询到一些想要的信息。也有可能是反过来查询。这个需要根据实际情况进行查询选择。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值