美文网首页
一个 NSOject 对象所占内存大小 ? (64bits)

一个 NSOject 对象所占内存大小 ? (64bits)

作者: 游城十代2dai | 来源:发表于2020-04-05 13:58 被阅读0次
    1. 系统实际分配了 16 字节给 NSOject对象, 通过 malloc_size 函数获得, 查看源码
      )可以知道平台底层对分配内存空间做了对齐操作, 在 libmalloc 中的宏定义 NANO_MAX_SIZE = 256 是说 nano 这种分配空间方式里面最大分配 256 个字节, 备注里面有说是 16 的倍数
    2. NSOject 对象内部使用了 8 个字节, 通过 class_getInstanceSize 函数获得, 也就是说该函数获取的是最少需要的字节数, 是结构体对齐后的字节数, 与 sizeof 计算出来的数值一样
    • iOS 源码地址
    https://opensource.apple.com/tarballs
    
    • 转 iOS --> 64bits (arm64), 可以查看翻译成 C 的代码 中类的结构体
    $ xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
    # 转换 LLVM 命令
    $ clang -emit-llvm -S main.m 
    
    • 记得引入以下头文件
    #import <objc/runtime.h>
    #import <malloc/malloc.h>
    
    • 下面是我的测试代码, 放入 main.m 就可以
    
    #import <Foundation/Foundation.h>
    #import <objc/runtime.h>
    #import <malloc/malloc.h>
    
    @interface Student : NSObject
    {
        @public
        int _no;
        int _age;
    }
    @end
    @implementation Student
    @end
    
    /**
     * 一个 NSOject 对象所占内存大小 ? (64bits)
     * 系统分配了 16 字节给 NSOject 对象, 通过 malloc_size 函数获得
     * 但 NSOject 对象内部使用了 8 个字节, 通过 class_getInstanceSize 函数获得
     */
    void objc_instance_size (void);
    void student_instance_size (void);
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // insert code here...
            objc_instance_size();
            student_instance_size();
        }
        return 0;
    }
    
    /**
     * NSOject_Implementation
     * clang 编译后的 NSObject 实质为一个 C 的结构体如下
     * 数据结构
     */
    struct NSObject_IMPL {
        Class isa;
        //    typedef struct objc_class *Class;
        //    Class 指向结构体的指针
        //    指针在 64bits 上是 8 个字节
    };
    // NSObject.h
    //@interface NSObject <NSObject> {
    //    Class isa  OBJC_ISA_AVAILABILITY;
    //}
    void objc_instance_size () {
        
        NSObject *objc = NSObject.alloc.init;
        
        size_t objc_sizes = class_getInstanceSize(objc.class);
        // 获取 NSOject 类的实例对象中成员变量内存对齐后所占内存的大小(最少需要的空间, 值和 sizeof 计算的一样)
        NSLog(@"objc_sizes  => %zd", objc_sizes);
        /* class_getInstanceSize 源码中调用了下面的函数, 所以是对齐过的 ivar size
         // Class's ivar size rounded up to a pointer-size boundary.
         uint32_t alignedInstanceSize() {
             return word_align(unalignedInstanceSize());
         }
         */
        
        size_t malloc_sizes = malloc_size((__bridge const void *)(objc));
        // 获取 objc 指针指向所占内存的大小(实际开辟的, 通过源码可以看到 iOS 是 16 的倍数对齐 libmalloc 中的宏定义 NANO_MAX_SIZE)
        NSLog(@"malloc_sizes => %zd", malloc_sizes);
        /* 在 _class_createInstanceFromZone 也就是 allocWithZone 的底层实现中调用了以下函数来计算实例大小
         
         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;
         }
         */
            
        
        // OC 转成 CPP, 不同的平台转换出来的代码是不一样的
        // 转 iOS  -> 64bits (arm64)
        // xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
        // 源码: https://opensource.apple.com/tarballs
    
    }
    
    
    void student_instance_size () {
        /* clang 编译后的 Student 实质为一个 C 的结构体如下 */
        struct Student_IMPL {
            struct NSObject_IMPL NSObject_IVARS;
            int _no;
            int _age;
        };
            
        Student *std = Student.alloc.init;
        std->_no = 2;
        std->_age = 10;
        
        size_t malloc_sizes = malloc_size((__bridge const void *)(std));
        // 获取 std 指针指向所占内存的大小
        NSLog(@"std_malloc_sizes => %zd", malloc_sizes);
        
        struct Student_IMPL *std_imp = (__bridge struct Student_IMPL *)(std);
        NSLog(@"std_imp->_no: %d \t std_imp->_age: %d", std_imp->_no, std_imp->_age);
    }
    
    
    

    相关文章

      网友评论

          本文标题:一个 NSOject 对象所占内存大小 ? (64bits)

          本文链接:https://www.haomeiwen.com/subject/veduphtx.html