本篇文章針對類的結(jié)構(gòu)進(jìn)行初步的分析定页,對之前學(xué)習(xí)的內(nèi)容做一個(gè)小小的總結(jié)迅耘。
文章的分析主要是利用lldb斷點(diǎn)調(diào)試,通過查看類的內(nèi)存空間冤馏,分析定位類的實(shí)例變量日麸、屬性、對象方法和類方法在編譯之后的存儲位置逮光。
1代箭、首先在main方法中添加代碼,并且在NSLog那一行打上斷點(diǎn):
涕刚、嗡综、、
int?main(int?argc,const?char* argv[]) {
? ? @autoreleasepool {
? ? ? ? LGPerson*person = [LGPerson alloc];
? ? ? ? Class pClass ? =object_getClass(person);
? ? ? ? NSLog(@"%@ - %p",person,pClass);
? ? }
?? ?return0;
}
杜漠、极景、、
2驾茴、然后通過命令查看pClass的內(nèi)存地址:
盼樟、、锈至、
?x/4gx pClass
0x1000023b0: 0x001d800100002389 0x0000000100afe140
0x1000023c0: 0x00000001003a1270 0x0000000000000000
晨缴、、峡捡、
通過分析objc_class結(jié)構(gòu)體的定義:
击碗、、棋返、
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的內(nèi)存初始位置: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.猜測:有關(guān)屬性挥转、方法和協(xié)議的相關(guān)信息分別存在$3的properties海蔽、methods和protocols中共屈,但是通過p(po)命令查看,猜測錯(cuò)誤党窜。它們真正的位置在$3的ro里面拗引,下面去一一驗(yàn)證。
5.驗(yàn)證
幌衣、矾削、、
(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里面,而是保存在元類里面惹骂。