1. alloc和init
先自定义一个宏用于控制台打印
#ifdef DEBUG
#define PFLog(format, ...) printf("%s\n", [[NSString stringWithFormat:format, ## __VA_ARGS__] UTF8String]);
#else
#define PFLog(format, ...);
#endif
执行下面的测试代码,
- (void)testAlloc {
PFPerson *t1 = [PFPerson alloc];
PFPerson *t2 = [t1 init];
PFPerson *t3 = [t1 init];
PFPerson *s1 = [PFPerson alloc];
PFPerson *s2 = [s1 init];
PFPerson *s3 = [s1 init];
NSLog(@"t1🐶%@🐶%p🐶%p", t1, t1, &t1);
NSLog(@"t2🐶%@🐶%p🐶%p", t2, t2, &t2);
NSLog(@"t3🐶%@🐶%p🐶%p", t3, t3, &t3);
NSLog(@"s1🐶%@🐶%p🐶%p", s1, s1, &s1);
NSLog(@"s2🐶%@🐶%p🐶%p", s2, s2, &s2);
NSLog(@"s3🐶%@🐶%p🐶%p", s3, s3, &s3);
}
打印信息
t1🐶<PFPerson: 0x600003c6c0a0>🐶0x600003c6c0a0🐶0x7ffeef2f10b8
t2🐶<PFPerson: 0x600003c6c0a0>🐶0x600003c6c0a0🐶0x7ffeef2f10b0
t3🐶<PFPerson: 0x600003c6c0a0>🐶0x600003c6c0a0🐶0x7ffeef2f10a8
s1🐶<PFPerson: 0x600003c6c0e0>🐶0x600003c6c0e0🐶0x7ffeef2f10a0
s2🐶<PFPerson: 0x600003c6c0e0>🐶0x600003c6c0e0🐶0x7ffeef2f1098
s3🐶<PFPerson: 0x600003c6c0e0>🐶0x600003c6c0e0🐶0x7ffeef2f1090
仔细分析得出:
- alloc会分配内存,而init啥也不干
- 栈区(这里存放指针)的内存分配从高地址到低地址,而堆区(这里存放实例对象)则是从低地址到高地址
2. 探究OC源码的3种方式
2.1 方法1:符号断点
将鼠标悬停在step into
按钮上,可以看到该按钮的操作提示:
step into
step into instruction (hold Control)
step into thread (hold Control-Shift)
于是我们按住Control
点击step into
按钮,一步一步向下进行,
找到了objc_alloc
,这里打一个符号断点
点击Continue program execution
,于是我们得到了objc_alloc
所在的库是libobjc.A.dylib
2.2 方法2:查看汇编代码,分析调用链
找到objc_alloc
,接下来就好办了,可以参考 2.1
2.3 编译objc源码,直接调试
通过2.1
、2.2
都很容易得知,objc_alloc
是libobjc.A.dylib
库中的一个方法,接下来可以到苹果官网下载这个库的开源代码,通过编译、解决错误使之运行起来,更方便地查看alloc底层的运行过程。