64位架构下实例对象占用内存

2019-09-27  本文已影响0人  我才是臭吉吉

参考链接:

我们知道OC实例对象的指针占用的内存为8字节(isa指针,或者说是objc_class结构体指针)。

但是,实际上一个OC对象的内存占用为至少16字节

在OC对象alloc方法的源码中,可以看到:

static __attribute__((always_inline)) 
id
_class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone, 
                              bool cxxConstruct = true, 
                              size_t *outAllocatedSize = nil)
{
    if (!cls) return nil;

    assert(cls->isRealized());

    // Read class's info bits all at once for performance
    bool hasCxxCtor = cls->hasCxxCtor();
    bool hasCxxDtor = cls->hasCxxDtor();
    bool fast = cls->canAllocNonpointer();

    size_t size = cls->instanceSize(extraBytes);
    if (outAllocatedSize) *outAllocatedSize = size;

    id obj;
    if (!zone  &&  fast) {
        obj = (id)calloc(1, size);
        if (!obj) return nil;
        obj->initInstanceIsa(cls, hasCxxDtor);
    } 
    else {
        if (zone) {
            obj = (id)malloc_zone_calloc ((malloc_zone_t *)zone, 1, size);
        } else {
            obj = (id)calloc(1, size);
        }
        if (!obj) return nil;

        // Use raw pointer isa on the assumption that they might be 
        // doing something weird with the zone or RR.
        obj->initIsa(cls);
    }

    if (cxxConstruct && hasCxxCtor) {
        obj = _objc_constructOrFree(obj, cls);
    }

    return obj;
}

其中,instanceSize函数的实现为:

size_t instanceSize(size_t extraBytes) {
     size_t size = alignedInstanceSize() + extraBytes;
      // CF requires all objects be at least 16bytes.
      if (size < 16) size = 16;
      return size; 
}

可以看出,在分配内存时,OC对象的最小内存占用为16字节

而通过查看内存分配可知,OC对象的内存是按照16字节进行对齐的

因此,在当类中存在其他属性时,在内存分配时,不足的需要按16字节进行补齐。

例如:

@interface TestClass : NSObject

@property (nonatomic, assign) NSInteger age;
@property (nonatomic, assign) int height;
@property (nonatomic, assign) int row;

@end


int main(int argc, const char * argv[]) {
    @autoreleasepool {
        TestClass *obj = [TestClass new];
        obj.age = 4;
        obj.height = 5;
        obj.row = 6;
        
        NSLog(@"类的实例尺寸----%zd", class_getInstanceSize(obj.class));
        
        const void *objPtr = (__bridge const void *)obj;
        NSLog(@"类实例分配的空间====%zd", malloc_size(objPtr));
    }
    return 0;
}

输出为:

2019-09-12 11:23:08.682507+0800 AlgorithmLearning[30513:6166466] 类的实例尺寸----24
2019-09-12 11:23:08.682960+0800 AlgorithmLearning[30513:6166466] 类实例分配的空间====32

通过查看obj的内存分配可以看到(lldb的”x 地址“指令):

(lldb) x 0x000000010102be80
0x10102be80: 09 25 00 00 01 80 1d 00 05 00 00 00 06 00 00 00 .%..............
0x10102be90: 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................

可以看出,前8字节为objc_class指针,后面依次为4字节的height,4字节的row,之后是8字节的age。
在前16字节中,因为占用内存已满,因此,要开辟第二行来存储age,所以,实例的尺寸为 8 + 4 + 4 + 8 = 24 字节。但由于内存分配按照16字节对齐,因此第二行还要补齐缺失的8字节,因此obj实例实际分配的内存空间为 24 + 8 = 32字节。

上一篇 下一篇

猜你喜欢

热点阅读