阅读 132

runtime01 - 对象内存布局

Obj-C NSObject对象的内存布局是怎么样的? 占据多少内存

实际上类似一个只包含一个成员变量isa指针的结构体

struct NSObject_IMPL {     Class isa; } 复制代码

Obj-C NSObject对象占据多少内存

有8字节就够用, 但是在alloc的时候, 系统会根据 对象的instancesize 和 16来取最大值, 所以也会申请16字节的大小

一个普通对象的内存布局是怎么样的

struct NSObject_IMPL {     Class isa; }; struct Person_IMPL {     struct NSObject_IMPL NSObject_IVARS;     int _age; }; struct Student_IMPL {     struct Person_IMPL Person_IVARS;     long long _height; }; 复制代码

@interface Person: NSObject {     int _age; } @end @interface Student: Person {     long long _height; } @end 复制代码

Demo

// xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main_arm64.cpp #import <Foundation/Foundation.h> #import <objc/runtime.h> #import <malloc/malloc.h> struct NSObject_IMPL {     Class isa; }; struct Person_IMPL {     struct NSObject_IMPL NSObject_IVARS;     int _age; }; struct Student_IMPL {     struct Person_IMPL Person_IVARS;     long long _height; }; @interface Person: NSObject { @public     int _age; } @end @implementation Person @end @interface Student: Person { @public     long long _height; } @end @implementation Student @end int main(int argc, const char * argv[]) {     @autoreleasepool {         // allocWithZone:时分配给对象的最小空间为16, 不足16的, 也会返回16         // 为了效率, iOS分配给对象的空间都是16的倍数         // class_getInstanceSize 获取对象需要的最小空间         // malloc_size           获取对象真实的占用空间         NSObject *obj = [NSObject new];         NSLog(@"%zu, %zu",               class_getInstanceSize([NSObject class]), // 只有一个isa指针, 所以只需要8               malloc_size((__bridge const void *)obj)); // allocWithZone:时分配给对象的最小空间为16, 不足16的, 也会返回16         Person *person = [Person new];         NSLog(@"%zu, %zu",               class_getInstanceSize([Person class]),  // 只有一个isa指针,和一个int指针, 但是需要内存对齐, 所以需要16               malloc_size((__bridge const void *)person)); // allocWithZone:时分配给对象的最小空间为16, 不足16的, 也会返回16         Student *student = [Student new];         NSLog(@"%zu, %zu",               class_getInstanceSize([Student class]), // 因为内存对齐的原因, 需要24               malloc_size((__bridge const void *)student)); // iOS分配给对象的空间都是16的倍数, 所以是32         student->_height = 100;         student->_age = 50;         struct Student_IMPL *stu = (__bridge struct Student_IMPL *)(student);     }     return 0; } // **2021-09-27 11:09:37.980596+0800 TestOC[40849:5211544] 8, 16** // **2021-09-27 11:09:37.980885+0800 TestOC[40849:5211544] 16, 16** // **2021-09-27 11:09:37.980923+0800 TestOC[40849:5211544] 32, 32** 复制代码

源码

static ALWAYS_INLINE id _class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone,                               int construct_flags = OBJECT_CONSTRUCT_NONE,                               bool cxxConstruct = true,                               size_t *outAllocatedSize = nil) {     ASSERT(cls->isRealized());     // Read class's info bits all at once for performance     bool hasCxxCtor = cxxConstruct && cls->hasCxxCtor();     bool hasCxxDtor = cls->hasCxxDtor();     bool fast = cls->canAllocNonpointer();     size_t size; // 注意一下这个方法     size = cls->instanceSize(extraBytes);     if (outAllocatedSize) *outAllocatedSize = size;     id obj;     if (zone) {         obj = (id)malloc_zone_calloc((malloc_zone_t *)zone, 1, size);     } else {         obj = (id)calloc(1, size);     }     if (slowpath(!obj)) {         if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {             return _objc_callBadAllocHandler(cls);         }         return nil;     }     if (!zone && fast) {         obj->initInstanceIsa(cls, hasCxxDtor);     } else {         // Use raw pointer isa on the assumption that they might be         // doing something weird with the zone or RR.         obj->initIsa(cls);     }     if (fastpath(!hasCxxCtor)) {         return obj;     }     construct_flags |= OBJECT_CONSTRUCT_FREE_ONFAILURE;     return object_cxxConstructFromClass(obj, cls, construct_flags); } inline size_t instanceSize(size_t extraBytes) const {     if (fastpath(cache.hasFastInstanceSize(extraBytes))) {         return cache.fastInstanceSize(extraBytes);     }     size_t size = alignedInstanceSize() + extraBytes;     // CF requires all objects be at least 16 bytes.     if (size < 16) size = 16;     return size; }


作者:潘森
链接:https://juejin.cn/post/7025891345965252645


文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐