美文网首页iOS学习
iOS-底层原理04-结构体嵌套结构内存对齐

iOS-底层原理04-结构体嵌套结构内存对齐

作者: 一亩三分甜 | 来源:发表于2020-09-09 01:23 被阅读0次

    《iOS底层原理文章汇总》

    类分析

    1.获取对象的isa,得到类信息

    (lldb) x/4gx person
    0x1007041a0: 0x001d8001000021a9 0x0000000000000000
    0x1007041b0: 0x00007fff8a1bc860 0x000000010063ec10
    (lldb) p/x 0x001d8001000021a9 & 0x00007ffffffffff8ULL
    (unsigned long long) $1 = 0x00000001000021a8
    (lldb) po 0x00000001000021a8
    DCPerson
    

    I. 查看类的地址,类有关于类的内存分布

    1.通过打印isa

    (lldb) x 0x00000001000021a8
    0x1000021a8: 80 21 00 00 01 00 00 00 40 61 33 00 01 00 00 00  .!......@a3.....
    0x1000021b8: d0 03 33 00 01 00 00 00 00 00 00 00 10 80 00 00  ..3.............
    

    2.通过打印类.class

    (lldb) x DCPerson.class
    0x1000021a8: 80 21 00 00 01 00 00 00 40 61 33 00 01 00 00 00  .!......@a3.....
    0x1000021b8: d0 03 33 00 01 00 00 00 00 00 00 00 10 80 00 00  ..3.............
    

    3.通过runtime底层api打印object_getClass(对象)

    (lldb) x object_getClass(person)
    0x1000021a8: 80 21 00 00 01 00 00 00 40 61 33 00 01 00 00 00  .!......@a3.....
    0x1000021b8: d0 03 33 00 01 00 00 00 00 00 00 00 10 80 00 00  ..3.............
    

    II. 查看isa的关于类的内存地址的内存分布,与上MASK和不与上MASK的值是一样的,最后得到的首地址的值还为isa指针,指向类

    (lldb) x/4gx 0x00000001000021a8
    0x1000021a8: 0x0000000100002180 0x0000000100336140
    0x1000021b8: 0x00000001003303d0 0x0000801000000000
    
    (lldb) po 0x0000000100002180
    DCPerson
    
    (lldb) p/x 0x0000000100002180 & 0x00007ffffffffff8ULL
    (unsigned long long) $6 = 0x0000000100002180
    (lldb) po 0x0000000100002180
    DCPerson
    

    两个内存地址的值(0x00000001000021a8和0x0000000100002180)都是DCPerson???这是为什么呢,到底哪一个是DCPerson呢???

    于是就有元类的概念--系统提供元类,对象-isa-类(对象)->元类,接下来会有方法,协议,属性的归属,元类的定义和创建都是由编译器自动完成,类方法存储在元类里面

    • 1.查看元类的内存信息
    (lldb) x/4gx DCPerson.class
    0x1000021a8: 0x0000000100002180 0x0000000100336140
    0x1000021b8: 0x00000001003303d0 0x0000801000000000
    (lldb) p/x 0x0000000100002180 & 0x00007ffffffffff8ULL
    (unsigned long long) $9 = 0x0000000100002180
    (lldb) x/4gx 0x0000000100002180
    0x100002180: 0x00000001003360f0 0x00000001003360f0
    0x100002190: 0x0000000100706a90 0x0004e03100000007
    
    • 2.再往下查看根元类的内存信息
    (lldb) p/x 0x00000001003360f0 & 0x00007ffffffffff8ULL
    (unsigned long long) $10 = 0x00000001003360f0
    (lldb) x/4gx 0x00000001003360f0
    0x1003360f0: 0x00000001003360f0 0x0000000100336140
    0x100336100: 0x0000000100782b30 0x0004e03100000007
    (lldb) po 0x00000001003360f0
    NSObject
    

    和本身的系统的NSObject.class不是用一个

    (lldb) po 0x00000001003360f0
    NSObject
    
    (lldb) po NSObject.class
    NSObject
    
    (lldb) p/x NSObject.class
    (Class) $13 = 0x0000000100336140 NSObject
    

    面试题:NSObject类存在几份,类的信息在内存中永远只存在一份

    isa 对象 -> 类(DCPerson) -> 元类(DCPerson) -> NSObject(根元类) -> NSObject(根元类)

    • 3.分析类对象内存存在个数
    void lgTestClassNum(){
        Class class1 = [DCPerson class];
        Class class2 = [DCPerson alloc].class;
        Class class3 = object_getClass([DCPerson alloc]);
        Class class4 = [DCPerson alloc].class;
        NSLog(@"\n%p-\n%p-\n%p-\n%p",class1,class2,class3,class4);
    }
    0x1000020f0-
    0x1000020f0-
    0x1000020f0-
    0x1000020f0
    
    • 4.上面得出的不是NSObject的类,而是NSObject的元类,也叫根元类,地址0x00000001003360f0是一样的。验证如下:
    根元类@2x.png
    (lldb) po 0x00000001003360f0
    NSObject
    
    (lldb) po NSObject.class
    NSObject
    
    (lldb) p/x NSObject.class
    (Class) $13 = 0x0000000100336140 NSObject
    (lldb) x/4gx 0x0000000100336140
    0x100336140: 0x00000001003360f0 0x0000000000000000
    0x100336150: 0x000000010067fae0 0x0001801000000003
    (lldb) p/x 0x00000001003360f0 & 0x00007ffffffffff8ULL
    (unsigned long long) $14 = 0x00000001003360f0
    (lldb) po 0x00000001003360f0
    NSObject
    
    • 5.继续往下探究:查看根元类的isa指向的类的内存信息
    (lldb) x/4gx DCPerson.class
    0x1000021a8: 0x0000000100002180 0x0000000100336140
    0x1000021b8: 0x00000001003303d0 0x0000801000000000
    (lldb) p/x 0x0000000100002180 & 0x00007ffffffffff8ULL
    (unsigned long long) $9 = 0x0000000100002180
    (lldb) x/4gx 0x0000000100002180
    0x100002180: 0x00000001003360f0 0x00000001003360f0
    0x100002190: 0x0000000100706a90 0x0004e03100000007
    (lldb) p/x 0x00000001003360f0 & 0x00007ffffffffff8ULL
    (unsigned long long) $10 = 0x00000001003360f0
    (lldb) x/4gx 0x00000001003360f0
    0x1003360f0: 0x00000001003360f0 0x0000000100336140
    0x100336100: 0x0000000100782b30 0x0004e03100000007
    (lldb) po 0x00000001003360f0
    NSObject
    
    (lldb) po NSObject.class
    NSObject
    
    (lldb) p/x NSObject.class
    (Class) $13 = 0x0000000100336140 NSObject
    (lldb) x/4gx 0x0000000100336140
    0x100336140: 0x00000001003360f0 0x0000000000000000
    0x100336150: 0x000000010067fae0 0x0001801000000003
    (lldb) p/x 0x00000001003360f0 & 0x00007ffffffffff8ULL
    (unsigned long long) $14 = 0x00000001003360f0
    (lldb) po 0x00000001003360f0
    NSObject
    
    (lldb) x/4gx 0x00000001003360f0
    0x1003360f0: 0x00000001003360f0 0x0000000100336140
    0x100336100: 0x0000000100782b30 0x0005e03100000007
    (lldb) p/x 0x00000001003360f0 & 0x00007ffffffffff8ULL
    (unsigned long long) $16 = 0x00000001003360f0
    (lldb) po 0x00000001003360f0
    NSObject
    
    (lldb) x/4gx 0x00000001003360f0
    0x1003360f0: 0x00000001003360f0 0x0000000100336140
    0x100336100: 0x0000000100782b30 0x0005e03100000007
    (lldb) p/x 0x00000001003360f0 & 0x00007ffffffffff8ULL
    (unsigned long long) $18 = 0x00000001003360f0
    (lldb) po 0x00000001003360f0
    NSObject
    
    根元类指向根元类@2x.png

    isa指向关系

    只有NSObject少了一步元类的指向


    isa指向图@2x.png
    void lgTestNSObject(){
        //NSObject实例对象
        NSObject *object1 = [NSObject alloc];
        //NSObject类
        Class class = object_getClass(object1);
        //NSObject元类
        Class metaClass = object_getClass(class);
        //NSObject根元类
        Class rootMetaClass = object_getClass(metaClass);
        //NSObject根根元类
        Class rootRootMetaClass = object_getClass(rootMetaClass);
        NSLog(@"\n%p 实例对象\n%p 类\n%p 元类\n%p 根元类\n%p 根根元类",object1,class,metaClass,rootMetaClass,rootRootMetaClass);;
    }
    0x100479120 实例对象
    0x7fff92977118 类
    0x7fff929770f0 元类
    0x7fff929770f0 根元类
    0x7fff929770f0 根根元类
    
    • 6.实例对象之间根本没有任何关系,即没有继承关系,继承关系来自于类,只有类才有继承关系,根元类指向NSObject
      DCTeacher(儿子) --> DCPerson(父亲) --> NSObject --> (isa) nil 0-1
      teacher继承于person,查看person和teacher的实例对象,类,元类,根元类的内存地址


      isa流程图.png
    void lgInherit(){
        //DCPerson实例对象
        DCPerson *person = [DCPerson alloc];
        //DCPerson类
        Class personClass = object_getClass(person);
        //DCPerson元类
        Class personMetaClass = object_getClass(personClass);
        //DCPerson根元类
        Class personRootMetaClass = object_getClass(personMetaClass);
        //DCPerson根根元类
        Class personRootRootMetaClass = object_getClass(personRootMetaClass);
        NSLog(@"\n%p 实例对象\n%p 类\n%p 元类\n%p 根元类\n%p 根根元类\n",person,personClass,personMetaClass,personRootMetaClass,personRootRootMetaClass);
        
        //DCTeacher实例对象
        DCPerson *teacher = [DCTeacher alloc];
        //DCTeacher类
        Class teacherClass = object_getClass(teacher);
        //DCTeacher元类
        Class teacherMetaClass = object_getClass(teacherClass);
        //DCTeacher根元类
        Class teacherRootMetaClass = object_getClass(teacherMetaClass);
        //DCTeacher根根元类
        Class teacherRootRootMetaClass = object_getClass(teacherRootMetaClass);
        NSLog(@"\n%p 实例对象\n%p 类\n%p 元类\n%p 根元类\n%p 根根元类",teacher,teacherClass,teacherMetaClass,teacherRootMetaClass,teacherRootRootMetaClass);
    }
    2020-10-04 15:33:51.316625+0800 iOS-isa分析[46409:2533244] 
    0x10040aea0 实例对象
    0x100002198 类
    0x100002170 元类
    0x7fff929770f0 根元类
    0x7fff929770f0 根根元类
    
    2020-10-04 15:33:51.316711+0800 iOS-isa分析[46409:2533244] 
    0x100704c40 实例对象
    0x1000021e8 类
    0x1000021c0 元类
    0x7fff929770f0 根元类
    0x7fff929770f0 根根元类
    

    通过clang编译成C++文件发现,对象和类的底层都是结构体,objc_object(根对象) vs object_class(Class) (NSObject) (isa)

    NSObject类 VS 对象: struct objc_class:objc_object

    对象 + 类 + 元类 都有isa,objc_object对象的关系,NSObject(OC),objc_object(C/C++)结构体,

    struct objc_class *Class定义一个Class()


    objc_object@2x.png

    类的内存分布(p/x--p为打印,x为以十六进制打印当前内存信息)

    • 1.查看类的内存信息
    (lldb) x/4gx DCPerson.class
    0x1000021a8: 0x0000000100002180 0x0000000100336140
    0x1000021b8: 0x00000001003303d0 0x0000801000000000
    (lldb) po 0x0000000100336140
    NSObject
    
    (lldb) p/x NSObject.class
    (Class) $23 = 0x0000000100336140 NSObject
    (lldb) 父类为NSObject
    
    • 2.查看类信息的源码
    struct objc_class : objc_object {
        // Class ISA;
        Class superclass;
        cache_t cache;             // formerly cache pointer and vtable
        class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
    
        class_rw_t *data() const {
            return bits.data();
        }
        void setData(class_rw_t *newData) {
            bits.setData(newData);
        }
    
        void setInfo(uint32_t set) {
            ASSERT(isFuture()  ||  isRealized());
            data()->setFlags(set);
        }
    
        void clearInfo(uint32_t clear) {
            ASSERT(isFuture()  ||  isRealized());
            data()->clearFlags(clear);
        }
    }
    
    8.gif
    object_class@2x.png

    类的methodlist,propertylist,ivarlist在哪儿???

    C语言中的内存平移

    • 1.通过内存地址平移获取数组中的值
            //普通指针
            int a = 10;
            int b = 10;
            DCNSLog(@"%d -- %p",a,&a);
            DCNSLog(@"%d -- %p",b,&b);
            
            //对象
            DCPerson *p1 = [DCPerson alloc];
            DCPerson *p2 = [DCPerson alloc];
            DCNSLog(@"%@ -- %p",p1,&p1);
            DCNSLog(@"%@ -- %p",p2,&p2);
            
            //数组指针
            int c[4] = {1,2,3,4};
            int * p = c;
            for (int i = 0; i<4; i++) {
                int value = c[i];
                int v = *(p+i);
                DCNSLog(@"%d",value);
                DCNSLog(@"%d",v);
            }
            NSLog(@"指针-内存偏移");
    //输出
    10 -- 0x7ffeefbff42c
    10 -- 0x7ffeefbff428
    <DCPerson: 0x100566bd0> -- 0x7ffeefbff420
    <DCPerson: 0x100565c90> -- 0x7ffeefbff418
    0x7ffeefbff440,0x7ffeefbff440,0x7ffeefbff440,0x7ffeefbff444,0x7ffeefbff448,0x7ffeefbff44c
    1
    1
    2
    2
    3
    3
    4
    4
    2020-10-04 19:06:42.214800+0800 iOS-内存偏移[59476:2804871] 指针-内存偏移
    

    DCPerson.class地址 - 平移 拿到所有的值

    怎么获取objc_class中的cache和bits的值呢???

    struct objc_class : objc_object {
        // Class ISA;
        Class superclass;
        cache_t cache;             // formerly cache pointer and vtable
        class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
    
        class_rw_t *data() const {
            return bits.data();
        }
        void setData(class_rw_t *newData) {
            bits.setData(newData);
        }
    
        void setInfo(uint32_t set) {
            ASSERT(isFuture()  ||  isRealized());
            data()->setFlags(set);
        }
    }
    
    类中的属性@2x.png
    objc_class内存分布@2x.png
    • 1.如果要知道bits的值,得先知道bits结构体属性ISA指针的大小(8字节),superclass的大小(8字节),cache的大小(未知),进行平移

    I 查看cache的大小

    struct cache_t {
    #if CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_OUTLINED
        explicit_atomic<struct bucket_t *> _buckets;
        explicit_atomic<mask_t> _mask;
    #elif CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16
        explicit_atomic<uintptr_t> _maskAndBuckets;
        mask_t _mask_unused;
        
        // How much the mask is shifted by.
        static constexpr uintptr_t maskShift = 48;
        
        // Additional bits after the mask which must be zero. msgSend
        // takes advantage of these additional bits to construct the value
        // `mask << 4` from `_maskAndBuckets` in a single instruction.
        static constexpr uintptr_t maskZeroBits = 4;
        
        // The largest mask value we can store.
        static constexpr uintptr_t maxMask = ((uintptr_t)1 << (64 - maskShift)) - 1;
        
        // The mask applied to `_maskAndBuckets` to retrieve the buckets pointer.
        static constexpr uintptr_t bucketsMask = ((uintptr_t)1 << (maskShift - maskZeroBits)) - 1;
        
        // Ensure we have enough bits for the buckets pointer.
        static_assert(bucketsMask >= MACH_VM_MAX_ADDRESS, "Bucket field doesn't have enough bits for arbitrary pointers.");
    #elif CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_LOW_4
        // _maskAndBuckets stores the mask shift in the low 4 bits, and
        // the buckets pointer in the remainder of the value. The mask
        // shift is the value where (0xffff >> shift) produces the correct
        // mask. This is equal to 16 - log2(cache_size).
        explicit_atomic<uintptr_t> _maskAndBuckets;
        mask_t _mask_unused;
    
        static constexpr uintptr_t maskBits = 4;
        static constexpr uintptr_t maskMask = (1 << maskBits) - 1;
        static constexpr uintptr_t bucketsMask = ~maskMask;
    #else
    #error Unknown cache mask storage type.
    #endif
        
    #if __LP64__
        uint16_t _flags;
    #endif
        uint16_t _occupied;
    }
    

    explicit_atomic<struct bucket_t *> _buckets; 泛型为结构体指针,8字节

    explicit_atomic<mask_t> _mask; mask_t为typedef uint32_t mask_t;为typedef unsigned int uint32_t;4字节

    uint16_t _flags; typedef unsigned short uint16_t;2字节

    uint16_t _occupied; 2字节

    综上cache的大小8+4+2+2=16字节

    要获取bits首地址需要平移ISA(8字节)+superclass(8字节)+cache(16) = 32字节,具体为首地址0x1000021b0平移32位得到0x1000021d0

    获取class_data_bits_t bits的值:打印出firstSubclass为DCTeacher

    DCPerson was compiled with optimization - stepping may behave oddly; variables may not be available.
    (lldb) x/4gx DCPerson.class
    0x1000021b0: 0x0000000100002188 0x0000000100336140
    0x1000021c0: 0x00000001003303d0 0x0000801000000000
    (lldb) p (class_data_bits_t *)0x1000021d0
    (class_data_bits_t *) $1 = 0x00000001000021d0
    (lldb) p $1->data()
    (class_rw_t *) $2 = 0x0000000101928700
    (lldb) p *$2
    (class_rw_t) $3 = {
      flags = 2148007936
      witness = 0
      ro_or_rw_ext = {
        std::__1::atomic<unsigned long> = 4294975624
      }
      firstSubclass = DCTeacher
      nextSiblingClass = NSUUID
    }
    
    9.gif

    往里探究ro_or_rw_ext

    (lldb) p $3.ro_or_rw_ext
    (explicit_atomic<unsigned long>) $4 = {
      std::__1::atomic<unsigned long> = 4294975624
    }
    
    • 1.查看class_rw_t源码
    struct class_rw_t {
        // Be warned that Symbolication knows the layout of this structure.
        uint32_t flags;
        uint16_t witness;
    #if SUPPORT_INDEXED_ISA
        uint16_t index;
    #endif
    
        explicit_atomic<uintptr_t> ro_or_rw_ext;
    
        Class firstSubclass;
        Class nextSiblingClass;
    
    private:
        using ro_or_rw_ext_t = objc::PointerUnion<const class_ro_t, class_rw_ext_t, PTRAUTH_STR("class_ro_t"), PTRAUTH_STR("class_rw_ext_t")>;
    
        const ro_or_rw_ext_t get_ro_or_rwe() const {
            return ro_or_rw_ext_t{ro_or_rw_ext};
        }
    
        void set_ro_or_rwe(const class_ro_t *ro) {
            ro_or_rw_ext_t{ro, &ro_or_rw_ext}.storeAt(ro_or_rw_ext, memory_order_relaxed);
        }
    
        void set_ro_or_rwe(class_rw_ext_t *rwe, const class_ro_t *ro) {
            // the release barrier is so that the class_rw_ext_t::ro initialization
            // is visible to lockless readers
            rwe->ro = ro;
            ro_or_rw_ext_t{rwe, &ro_or_rw_ext}.storeAt(ro_or_rw_ext, memory_order_release);
        }
    
        class_rw_ext_t *extAlloc(const class_ro_t *ro, bool deep = false);
    
    public:
        void setFlags(uint32_t set)
        {
            __c11_atomic_fetch_or((_Atomic(uint32_t) *)&flags, set, __ATOMIC_RELAXED);
        }
    
        void clearFlags(uint32_t clear) 
        {
            __c11_atomic_fetch_and((_Atomic(uint32_t) *)&flags, ~clear, __ATOMIC_RELAXED);
        }
    
        // set and clear must not overlap
        void changeFlags(uint32_t set, uint32_t clear) 
        {
            ASSERT((set & clear) == 0);
    
            uint32_t oldf, newf;
            do {
                oldf = flags;
                newf = (oldf | set) & ~clear;
            } while (!OSAtomicCompareAndSwap32Barrier(oldf, newf, (volatile int32_t *)&flags));
        }
    
        class_rw_ext_t *ext() const {
            return get_ro_or_rwe().dyn_cast<class_rw_ext_t *>(&ro_or_rw_ext);
        }
    
        class_rw_ext_t *extAllocIfNeeded() {
            auto v = get_ro_or_rwe();
            if (fastpath(v.is<class_rw_ext_t *>())) {
                return v.get<class_rw_ext_t *>(&ro_or_rw_ext);
            } else {
                return extAlloc(v.get<const class_ro_t *>(&ro_or_rw_ext));
            }
        }
    
        class_rw_ext_t *deepCopy(const class_ro_t *ro) {
            return extAlloc(ro, true);
        }
    
        const class_ro_t *ro() const {
            auto v = get_ro_or_rwe();
            if (slowpath(v.is<class_rw_ext_t *>())) {
                return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->ro;
            }
            return v.get<const class_ro_t *>(&ro_or_rw_ext);
        }
    
        void set_ro(const class_ro_t *ro) {
            auto v = get_ro_or_rwe();
            if (v.is<class_rw_ext_t *>()) {
                v.get<class_rw_ext_t *>(&ro_or_rw_ext)->ro = ro;
            } else {
                set_ro_or_rwe(ro);
            }
        }
    
        const method_array_t methods() const {
            auto v = get_ro_or_rwe();
            if (v.is<class_rw_ext_t *>()) {
                return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->methods;
            } else {
                return method_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->baseMethods()};
            }
        }
    
        const property_array_t properties() const {
            auto v = get_ro_or_rwe();
            if (v.is<class_rw_ext_t *>()) {
                return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->properties;
            } else {
                return property_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->baseProperties};
            }
        }
    
        const protocol_array_t protocols() const {
            auto v = get_ro_or_rwe();
            if (v.is<class_rw_ext_t *>()) {
                return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->protocols;
            } else {
                return protocol_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->baseProtocols};
            }
        }
    };
    

    类中添加一个属性一个成员变量,一个实例方法和一个类方法

    @interface DCPerson : NSObject{
        NSString *hobby;
    }
    @property(nonatomic,copy)NSString *kc_name;
    -(void)sayNB;
    +(void)say666;
    @end
    
    • 2.属性的值:有一个属性kc_name,和一个成员变量的hobby,目前只能打印kc_name的值
    (lldb) x/4gx DCPerson.class
    0x1000022c0: 0x0000000100002298 0x0000000100336140
    0x1000022d0: 0x00000001003303d0 0x0000802400000000
    (lldb) p (class_data_bits_t *)0x1000022e0
    (class_data_bits_t *) $1 = 0x00000001000022e0
    (lldb) p $1->data()
    (class_rw_t *) $2 = 0x0000000100678680
    (lldb) p $2->properties()
    (const property_array_t) $3 = {
      list_array_tt<property_t, property_list_t, RawPtr> = {
         = {
          list = {
            ptr = 0x00000001000021b8
          }
          arrayAndFlag = 4294975928
        }
      }
    }
    (lldb) p $3.list.ptr
    (property_list_t *const) $4 = 0x00000001000021b8
    (lldb) p *$4
    (property_list_t) $5 = {
      entsize_list_tt<property_t, property_list_t, 0, PointerModifierNop> = (entsizeAndFlags = 16, count = 1)
    }
    (lldb) p $5.get(0)
    (property_t) $6 = (name = "kc_name", attributes = "T@\"NSString\",C,N,V_kc_name")
    (lldb) p $5.get(1)
    Assertion failed: (i < count), function get, file /Users/cloud/Documents/iOS/0911/0911练习/iOS-isa指针/runtime/objc-runtime-new.h, line 479.
    error: Execution was interrupted, reason: signal SIGABRT.
    The process has been returned to the state before expression evaluation.
    

    count = 1为1表示仅有1个属性kc_name


    10.gif
    • 3.方法的值:count = 4,表明有4个方法,sayNB,属性的setter和getter方法,kc_name,setKc_name:,.cxx_destruct,C++位于OC底层,默认会自动添加方法,都是实例方法,并没有类方法say666()。
    (lldb) p/x DCPerson.class
    (Class) $0 = 0x00000001000022c0 DCPerson
    (lldb) p (class_data_bits_t *)0x00000001000022e0
    (class_data_bits_t *) $1 = 0x00000001000022e0
    (lldb) p $1->data()
    (class_rw_t *) $2 = 0x000000010089e5f0
    (lldb) p *$2
    (class_rw_t) $3 = {
      flags = 2148007936
      witness = 0
      ro_or_rw_ext = {
        std::__1::atomic<unsigned long> = 4294975680
      }
      firstSubclass = DCTeacher
      nextSiblingClass = NSUUID
    }
    (lldb) p $3.methods()
    (const method_array_t) $4 = {
      list_array_tt<method_t, method_list_t, method_list_t_authed_ptr> = {
         = {
          list = {
            ptr = 0x0000000100002108
          }
          arrayAndFlag = 4294975752
        }
      }
    }
    (lldb) p $4.list.ptr
    (method_list_t *const) $5 = 0x0000000100002108
    (lldb) p *$5
    (method_list_t) $6 = {
      entsize_list_tt<method_t, method_list_t, 4294901763, method_t::pointer_modifier> = (entsizeAndFlags = 26, count = 4)
    }
    (lldb) p $6.get(0)
    (method_t) $7 = {}
    (lldb) p $7.name()
    (SEL) $8 = "sayNB"
    (lldb) p $7.types()
    (const char *) $9 = 0x0000000100000f7c "v16@0:8"
    (lldb) p $6.get(1)
    (method_t) $10 = {}
    (lldb) p $10.name()
    (SEL) $11 = "kc_name"
    (lldb) p $10.types()
    (const char *) $12 = 0x0000000100000f90 "@16@0:8"
    (lldb) p $6.get(2)
    (method_t) $13 = {}
    (lldb) p $13.name()
    (SEL) $14 = "setKc_name:"
    (lldb) p $13.types()
    (const char *) $15 = 0x0000000100000f98 "v24@0:8@16"
    (lldb) p $6.get(3)
    (method_t) $16 = {}
    (lldb) p $16.name()
    (SEL) $17 = ".cxx_destruct"
    (lldb) p $16.types()
    (const char *) $18 = 0x0000000100000f7c "v16@0:8"
    (lldb) p $6.get(4)
    Assertion failed: (i < count), function get, file /Users/cloud/Documents/iOS/0911/0911练习/iOS-isa指针/runtime/objc-runtime-new.h, line 479.
    error: Execution was interrupted, reason: signal SIGABRT.
    The process has been returned to the state before expression evaluation.
    
    11.gif

    那成员变量和类方法在哪里查看呢???

    相关文章

      网友评论

        本文标题:iOS-底层原理04-结构体嵌套结构内存对齐

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