• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

2021-06-03 iOS的alloc的底层代码流程

互联网 diligentman 3天前 5次浏览

iOS的alloc的底层代码流程

前言

创建类的一个对象的时候,alloc的底层做了什么呢?今天就好好的研究一下。
测试代码

	LGPerson *p1 = [LGPerson alloc];
    LGPerson *p2 = [p1 init];
    LGPerson *p3 = [p1 init];
    
    NSLog(@"%@-%p-%p",p1,p1,&p1);
    NSLog(@"%@-%p-%p",p2,p2,&p2);
    NSLog(@"%@-%p-%p",p3,p3,&p3);

打印结果是:

<LGPerson: 0x600001218290>-0x600001218290-0x16ced7f48
<LGPerson: 0x600001218290>-0x600001218290-0x16ced7f40
<LGPerson: 0x600001218290>-0x600001218290-0x16ced7f38

alloc出来之后就有了一片内存空间,p1,p2,p3都有了一个指针地址,这3个指针地址同时指向这个内存空间,这3个所指的地址在栈里面,如:&p1。指向这个内存空间为堆。这3个对象为连续开辟,在栈里面是连续的指针。

三种方式查看底层代码及流程

在p1处,加个断点,重新运行,就会进入 -[ViewController viewDidLoad]:
看底层源码,及怎么走的:

一、结合符号断点

得到:libobjc.A.dylib`objc_alloc:
然后按 ctrl+setup into(xcode的打印区上面的向下的箭头), 进入objc_alloc。可以看到:
2021-06-03 iOS的alloc的底层代码流程
2021-06-03 iOS的alloc的底层代码流程

可以看到进入到了objc_alloc的一个函数。要看到底层的源码,怎么走的,需要加一个System Breakpoint断点,objc_alloc,然后点击 continue program execution按钮(右箭头),可以进入libobjc.A.dylib`objc_alloc:
的底层:
2021-06-03 iOS的alloc的底层代码流程
底层下一步是要到_objc_rootAllocWithZone。

二、结合汇编去看

汇编跟流程,加符号断点objc_alloc
选择上面的Debug-> Debug Workflow-> Always Show Disassembly是设置汇编显示:
2021-06-03 iOS的alloc的底层代码流程
可以看到下一步是到 symbol stub for:objc_alloc,在这里加个断点,点击continue program execution按钮,就到这一行了,再点击ctrl+setup into按钮,就又到了objc_alloc:
2021-06-03 iOS的alloc的底层代码流程

三、通过符号断点,确定未知

得到:libobjc.A.dylib`+[NSObject alloc]:
前提是:需要去苹果官网下载objc的源码(搜索objc可以找到)。

去掉汇编显示的,选择上面的Debug-> Debug Workflow-> Always Show Disassembly,反选。
加一个System Breakpoint断点,olloc。然后点击continue program execution按钮,到:libobjc.A.dylib`+[NSObject alloc]:
2021-06-03 iOS的alloc的底层代码流程
看源码:
2021-06-03 iOS的alloc的底层代码流程
2021-06-03 iOS的alloc的底层代码流程
2021-06-03 iOS的alloc的底层代码流程
可知:alloc -> _objc_rootAlloc -> callAlloc
callAlloc 中可以看到 _objc_rootAllocWithZoneobjc_msgSend两个方法,但是是那个先跑呢?
需要在p1处加个断点,运行,可以见到运行到alloc的地方。加System Breakpoint断点,分别是:_objc_rootAlloccallAlloc_objc_rootAllocWithZone这三个断点。
然后点击continue program execution按钮,到:
2021-06-03 iOS的alloc的底层代码流程
可以看到是先跑:_objc_rootAlloc,再跑:_objc_rootAllocWithZone,再跑:objc_msgSend的。

通过源码可以看到:
2021-06-03 iOS的alloc的底层代码流程
2021-06-03 iOS的alloc的底层代码流程
跑了:_objc_rootAllocWithZone,再跑:_class_createInstanceFromZone。在源码中运行,打断点运行到这里:LGPerson *p = [LGPerson alloc];
然后在==_class_createInstanceFromZone==
方法里面打断点:
2021-06-03 iOS的alloc的底层代码流程
可以看出size这里的cls->instanceSize是先计算出需要的内存空间大小。向下面走,到这里:

2021-06-03 iOS的alloc的底层代码流程
可以看到obj已经有了地址,但是obj却又没有使用过,可知是分配的是脏内存地址,没有被开辟出来。
接着往下走:
2021-06-03 iOS的alloc的底层代码流程
可以看到走到了calloc这里:
接着走:
2021-06-03 iOS的alloc的底层代码流程
可以看到obj的地址变了,有了一个新的地址,说明在calloc里面对obj进行了新的地址赋值。我们已知obj是一个对象,是一个类的对象,类的对象是isa。从地址上可知,当前地址还没有和类关联起来。
继续走:
2021-06-03 iOS的alloc的底层代码流程

走到了obj->initInstanceIsa这里。
继续走:

2021-06-03 iOS的alloc的底层代码流程
打印obj的地址,发现关联上了LGPerson的类。
然后就是对象返回类出去:
2021-06-03 iOS的alloc的底层代码流程

总结:
alloc的流程是:
alloc -> _objc_rootAlloc -> callAlloc -> _objc_rootAllocWithZone -> objc_msgSend。
其中跑完_objc_rootAllocWithZone -> _class_createInstanceFromZone, 之后是先cls->instanceSize,再是calloc里面给对象赋值新的内存地址,最后是obj->initInstanceIsa让对象的地址关联上了类。
alloc的流程研究已经完成,可知就是开辟一个内存并与类关联起来。


程序员灯塔
转载请注明原文链接:2021-06-03 iOS的alloc的底层代码流程
喜欢 (0)