(一)OC对象本质---内存布局

Apple OSS Distributions · GitHub
Apple Open Source    开源源码链接

面试题1

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

系统分配了16个字节给NSObject对象(通过malloc_size函数获得)
​​​​​​​但NSObject对象内部只使用了8个字节的空间(64bit环境下,可以通过class_getInstanceSize函数获得)

        

(一)OC对象本质---内存布局_第1张图片

  

1)OC中的对象、类主要是基于C\C++的结构体来实现的.C\C++的结构体支撑了我们的面向对象。
Class: 是一个指针  占8个字节。
NSObject *obj = [NSObject alloc ] init];
[NSObject alloc ] init] 就是 分配存储空间给结构体
分配完以后,还有一个指针*,利用这个指针要指向这个对象,就要把对象的内存地址赋值给这个指针。指针存储内存地址,才能找到那个对象。所以这个isa指针的地址,就是结构体在内存中的地址。
isa指针占用了8个字节,但是在alignedInstanceSize里面,小于16会强制使用16个字节。所以分配了16个字节。
如果没有强制16字节,也会有内存对齐规定。内存对齐:为了 提高CPU的访问速度,会进行内存对齐操作。结构体的最终大小必须是最大成员大小的倍数

结构体内存对齐:计算结构体大小的时候 ,内存对齐
操作系统内存对齐:苹果操作系统给分配内存的时候,也存在内存对齐的概念

2)  2个容易混淆的函数

  class_getInstanceSize:成员变量占用的大小(对齐过的)

    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() {
        return word_align(unalignedInstanceSize());
    }


  // May be unaligned depending on class's ivars.
    uint32_t unalignedInstanceSize() {
        assert(isRealized());
        return data()->ro->instanceSize;
    }

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

ps:
  NSLog(@"%zd", class_getInstanceSize([Student class]));   ---->24
​​​​​​​  NSLog(@"%zd", malloc_size((__bridge const void *)stu));  ----->32​​​​​​​

class_getInstanceSize

操作系统,堆空间里面,都是16的倍数。

传递24个字节给calloc,内存对齐后 分配的内存快大小是--->NANO_MAX_SIZE
​​​​​​​#define NANO_MAX_SIZE 256 /* Buckets sized {16, 32, 48, 64, 80, 96, 112, ...} */

id
class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone)
{
    return _class_createInstanceFromZone(cls, extraBytes, zone);
}





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;
}

(一)OC对象本质---内存布局_第2张图片

​​​​​​​

你可能感兴趣的:(ios)