本篇文章针对类的结构进行初步的分析,对之前学习的内容做一个小小的总结。
文章的分析主要是利用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里面,而是保存在元类里面。
网友评论