objc源码官方地址
分析源码,先从创建对象开始
LGPerson *p1 = [LGPerson alloc];
LGPerson *p2 = [p1 init];
LGPerson *p3 = [p1 init];
//输出 内容、内存地址、指针地址
LGNSLog(@"%@ - %p - %p",p1,p1,&p1);
LGNSLog(@"%@ - %p - %p",p2,p2,&p2);
LGNSLog(@"%@ - %p - %p",p3,p3,&p3);
打印结果:
<LGPerson: 0x6000028bcb40> - 0x6000028bcb40 - 0x7ffee41000e8
<LGPerson: 0x6000028bcb40> - 0x6000028bcb40 - 0x7ffee41000e0
<LGPerson: 0x6000028bcb40> - 0x6000028bcb40 - 0x7ffee41000d8

1、alloc做了什么?
开辟内存空间
2、init做了什么?
//init 没有对空间做任何修改
+ (id)init {
return (id)self;
}
3、new做了什么?
+ (id)new {
return [callAlloc(self, false) init];
}
// 等同于 (alloc + init)
//不建议直接new, 因为可能会重写 init ,init 可能会带参数
4、alloc怎么开辟空间的?
主要是 _class_createInstanceFromZone 的实现流程,分三步:
cls->instanceSize :计算需要的内存空间大小(16字节对齐)
calloc :向系统申请开辟内存,返回地址指针
obj->initInstanceIsa:将类和内存地址绑定在一起,实例的isa指向类
5、alloc 的流程图

6、栈内存 是连续的?
栈内存是连续的,一个对象是8字节
7、NSObject *objc = [NSObject alloc] 为什么没有进+ (id)alloc {..}方法?
NSObject.mm
//LLVM (编译启动): 任何级别调用的alloc方法,都会调用到objc_alloc方法
// Calls [cls alloc].
id objc_alloc(Class cls)
{
return callAlloc(cls, true/*checkNil*/, false/*allocWithZone*/);
}
扩展:
1、命令
bt:打印堆栈
x 地址: 查看当前地址的内存情况
x/4gx 地址: 以16进制的形式打印4个地址
x/8gx 地址: 以16进制的形式打印8个地址
po 变量:显示内存的内容
2、字节对齐
//字节对齐算法, 16的倍数
//1.方便速度便捷,2. 16更安全
static inline size_t align16(size_t x) {
return (x + size_t(15)) & ~size_t(15);
}
任何一个对象都有一个isa ,isa 占8字节,如果按8字节对齐,每个对象都紧诶着其他对象的isa,会容易出现混乱, 为了内存安全,预留空间。 为什么是16?一个对象8字节,以最小单元翻倍。因为如果以一个9或10就会很恶心,需要随时改变读取的长度。每次都按8或16来读,每次都读这么多,不会产生混乱。
3、看源码的3种方式
-
下符号断点
第一步:在[LGPerson alloc]加断点,并运行
第二步:下符号断点
第一步:[LGPerson alloc]加断点.png



-
control + (step into)
第一步:在[LGPerson alloc]加断点
第二步:control + (step into)
第三步:下符号断点
第二步:control + (step into).gif

-
最常用方法:汇编查看流程
第一步:在[LGPerson alloc]加断点
第二步:debug ->debug workflow -> always show assembly
第三步:下符号断点
第二步:打开汇编查看.png

网友评论