类的结构初探

本篇文章针对类的结构进行初步的分析,对之前学习的内容做一个小小的总结。

文章的分析主要是利用lldb断点调试,通过查看类的内存空间,分析定位类的实例变量、属性、对象方法和类方法在编译之后的存储位置。

1、首先在main方法中添加代码,并且在NSLog那一行打上断点:

、、、

int main(int argc,const char* argv[]) {

    @autoreleasepool {

        LGPerson*person = [LGPerson alloc];

        Class pClass   =object_getClass(person);

        NSLog(@"%@ - %p",person,pClass);

    }

    return0;

}

、、、

2、然后通过命令查看pClass的内存地址:

、、、

 x/4gx pClass

0x1000023b0: 0x001d800100002389 0x0000000100afe140

0x1000023c0: 0x00000001003a1270 0x0000000000000000

、、、

通过分析objc_class结构体的定义:

、、、

struct objc_class : objc_object {

    // Class ISA; // 8,继承自父类

    Class superclass; // 8

    cache_t cache;    // 16 不是8        // formerly cache pointer and vtable

    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags

    class_rw_t*data() { 

        returnbits.data();

    }

......

}

、、、

可以定位到bits的内存初始位置:0x1000023b0 + 20(偏移量)= 0x1000023d0

3、输入命令:

、、、

p (class_data_bits_t *)0x1000023d0

(class_data_bits_t *) $1 = 0x00000001000023d0

p $1->data()

(class_rw_t *) $2 = 0x0000000100f90810

p *$2

(class_rw_t) $3 = {

  flags = 2148139008

  version = 0

  ro = 0x0000000100002308

  methods = {

    list_array_tt = {

       = {

        list = 0x0000000100002240

        arrayAndFlag = 4294976064

      }

    }

  }

  properties = {

    list_array_tt = {

       = {

        list = 0x00000001000022f0

        arrayAndFlag = 4294976240

      }

    }

  }

  protocols = {

    list_array_tt = {

       = {

        list = 0x0000000000000000

        arrayAndFlag = 0

      }

    }

  }

  firstSubclass = nil

  nextSiblingClass = NSDate

  demangledName = 0x0000000000000000

}

、、、

4.猜测:有关属性、方法和协议的相关信息分别存在$3的properties、methods和protocols中,但是通过p(po)命令查看,猜测错误。它们真正的位置在$3的ro里面,下面去一一验证。

5.验证

、、、

(lldb) p *$3.ro

(const class_ro_t) $5 = {

  flags = 388

  instanceStart = 8

  instanceSize = 24

  reserved = 0

  ivarLayout = 0x0000000100001f89 "\x02"

  name = 0x0000000100001f80 "LGPerson"

  baseMethodList = 0x0000000100002240

  baseProtocols = 0x0000000000000000

  ivars = 0x00000001000022a8

  weakIvarLayout = 0x0000000000000000

  baseProperties = 0x00000001000022f0

}

p *$5.baseProperties

(property_list_t) $6 = {

  entsize_list_tt = {

    entsizeAndFlags = 16

    count = 1

    first = (name = "nickName", attributes = "T@\"NSString\",C,N,V_nickName")

  }

}

p *$5.baseMethodList

(method_list_t) $7 = {

  entsize_list_tt = {

    entsizeAndFlags = 26

    count = 4

    first = {

      name = "sayHello"

      types = 0x0000000100001f8b "v16@0:8"

      imp = 0x0000000100001b90 (LGTest`-[LGPerson sayHello] at LGPerson.m:13)

    }

  }

}

p *$5.ivars

(const ivar_list_t) $8 = {

  entsize_list_tt = {

    entsizeAndFlags = 32

    count = 2

    first = {

      offset = 0x0000000100002378

      name = 0x0000000100001e64 "hobby"

      type = 0x0000000100001fa6 "@\"NSString\""

      alignment_raw = 3

      size = 8

    }

  }

}

、、、

但是,类方法并没有保存在 baseMethodList里面,而是保存在元类里面。

但是,类方法并没有保存在 baseMethodList里面,而是保存在元类里面。

但是,类方法并没有保存在 baseMethodList里面,而是保存在元类里面。

你可能感兴趣的:(类的结构初探)