源码查找:苹果开源地址
先下载objc4-xxx.tar
开始
全局搜索alloc {,找到底层实现方法
20201118174435.jpg
image.png
最后看到的就是这些代码:
static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
if (slowpath(checkNil && !cls)) return nil;
#if __OBJC2__
if (fastpath(!cls->ISA()->hasCustomAWZ())) {
// No alloc/allocWithZone implementation. Go straight to the allocator.
// fixme store hasCustomAWZ in the non-meta class and
// add it to canAllocFast's summary
if (fastpath(cls->canAllocFast())) {
// No ctors, raw isa, etc. Go straight to the metal.
bool dtor = cls->hasCxxDtor();
id obj = (id)calloc(1, cls->bits.fastInstanceSize());
if (slowpath(!obj)) return callBadAllocHandler(cls);
obj->initInstanceIsa(cls, dtor);
return obj;
}
else {
// Has ctor or raw isa or something. Use the slower path.
id obj = class_createInstance(cls, 0);
if (slowpath(!obj)) return callBadAllocHandler(cls);
return obj;
}
}
#endif
// No shortcuts available.
if (allocWithZone) return [cls allocWithZone:nil];
return [cls alloc];
}
但是这么看各种if else是不是不爽,接下来通过汇编看看:
- debug在alloc方法行加上断点,run
-
如下图一次添加符号断点
20201118173456.jpg
- 终端执行register read (寄存器-简单理解 存储指针)如下:
(注意:执行前将符号榜断点只保留alloc的)
x0 = 0x00000001042d95e8 (void *)0x00000001042d95c0: ZKCPerson
x1 = 0x00000001c568183f
x2 = 0x0000000000000001
x3 = 0x000000016bb2de10
x4 = 0x0000000000000010
x5 = 0x000000016bb2da1f
x6 = 0x000000016bb2db10
x7 = 0x0000000000000000
x8 = 0x00000001c5681000
x9 = 0x0000000000000303
x10 = 0x00000002420cce4f
x11 = 0x0000000000000003
x12 = 0x0000000000000003
x13 = 0x0000000000000000
x14 = 0x00000000000000f2
x15 = 0x00000001cb12b198 (void *)0x00000001c568180f
x16 = 0x21512c8188dbe2e4 (0x0000000188dbe2e4) libobjc.A.dylib`+[NSObject alloc]
x17 = 0x0000000188dbe2e4 libobjc.A.dylib`+[NSObject alloc]
x18 = 0x0000000000000000
x19 = 0x0000000000000000
x20 = 0x0000000135e0a9d0
x21 = 0x00000001d7236000 _MergedGlobals.9 + 24
x22 = 0x00000001c5681f05
x23 = 0x0000000000000001
x24 = 0x0000000000000001
x25 = 0x00000001d4346000 UIKitCore`UIKeyboardSquishTransition._useInteractiveOpacity
x26 = 0x0000000135e08a10
x27 = 0x00000002834e6c40
x28 = 0x00000001c568b55a
fp = 0x000000016bb2dc80
lr = 0x00000001042d5e30 001`-[ViewController viewDidLoad] + 108 at ViewController.m:21:21
sp = 0x000000016bb2dc00
pc = 0x0000000188dbe2e4 libobjc.A.dylib`+[NSObject alloc]
cpsr = 0x40000000
因为OC方法有两个默认参数:
- id self
- _cmd 当前方法的selector
所以可以执行以下命令:只读x0 register read x0,结果如下:
(x0 第一个参数 -返回的时候 返回值的存储地方)
x0 = 0x00000001042d95e8 (void *)0x00000001042d95c0: ZKCPerson
继续执行: po 0x00000001042d95e8
po 0x00000001042d95e8
ZKCPerson
可以看到现在还没指针(alloc-申请空间-给指针地址)
- 增加符号断点_objc_rootAllocWithZone 进入后查看如下图:
20201118210836.jpg
在retab(返回对象)前增加断点,继续,执行register read x0
x0 = 0x0000000282f6c000
继续执行 po 0x0000000282f6c000
<ZKCPerson: 0x282f6c000>
可以看见现在person有了指针0x282f6c000
网友评论