oc对象窥探

121 阅读1分钟

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

如下

  NSobjiect *obj = [[NSobject alloc]init];

首先我们通过clang生成.cpp文件

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp

通过查看main-arm64.cpp我们可以找到如下结构体

struct NSObject_IMPL {

Class isa;

};

我们可以看到翻译成c\C++代码这个对象就是一个结构体然后里面放了一个isa指针 isa占8个字节在64位中,那是不是意味着这个对象就只占用8个字节? 我们可以打印

NSObject *obj = [[NSObject alloc]init];
NSLog(@"%zd",class_getInstanceSize([NSObject class]));
NSLog(@"%zd",malloc_size((__bridge const void *)(obj)));

可以得到打印如下:

WeChat8b360dfef42491466dfb1ea4dcac245d.png 为什么malloc_size会是16? 16个字节其实是系统分分配的具体我们可以查看allocwithzone源码:

id 
_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);
}

这里很明显 if (size < 16) size = 16; 小于16返回16 我们可以继续调试如下:

WeChatf2ae6f44ff5946443cf80ecb9368184e.png

我们可以看到实际是分配了16位的地址并且后8位地址都是 00 为什么class_getInstanceSize打印出来会是8? 这是我们可以看看苹果源码

size_t class_getInstanceSize(Class cls)

{

    if (!cls) return 0;

    return cls->alignedInstanceSize();

}

// Class's ivar size rounded up to a pointer-size boundary.

    uint32_t alignedInstanceSize() const {

        return word_align(unalignedInstanceSize());

    }

大家注意看注释所以大家应该就知道为什么是8了吧