Apple OSS Distributions · GitHub
Apple Open Source    开源源码链接
 面试题1
一个NSObject对象占用多少内存?
系统分配了16个字节给NSObject对象(通过malloc_size函数获得)
 但NSObject对象内部只使用了8个字节的空间(64bit环境下,可以通过class_getInstanceSize函数获得)

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



















