alloc底层探索

165 阅读2分钟

一.OC对象的初始化

image.png 结果:

image.png

alloc有了内存,有了指针的指向,init不会对内存指针进行操作。

对代码进行修改如下:

image.png 可以看到打印结果如下:

image.png

可得alloc出来一片内存空间,p1,p2,p3为3个指针地址同时指向同一片内存空间,但地址是在栈里面,在栈中是连续的指针,相隔8字节。

1.alloc怎么做到的呢,init有什么用?

  • 三种分析方法 (1)断点跟踪法 ibobjc.A.dylib`objc_alloc:

在代码中打断点 image.png 运行后在断点处停顿,

image.png 进入到

image.png 然后利用添加symbolic Breakpoint来进入底层源码

image.png

image.png

(2)debug汇编法 objc_alloc

截屏2021-06-06 下午10.33.06.png 进入X86底层汇编

image.png 继续断点到

image.png (3)已知符号断点法 libobjc.A.dylib`+[NSObject alloc]:

截屏2021-06-06 下午10.47.38.png 然后断点下一步可进入

image.png

  • open source (1)首先进入到alloc函数的源码

image.png (2)在alloc源码中,再进入到_objc_rootAlloc中,可以看到

image.png (3)同样的操作我们进入到callAlloc方法中

image.png 这里出现了分叉,为了分析到底走什么方法,则将以上流程都下好相应的符号断点,

image.png 但还不能直接运行, register read x0会报错因为我们研究的是子类而不是父类,需要先运行到LGPerson的断点区域然后再打开运行断点

image.png

  • 底层方法的编译和调试

编译器优化 arm64中,x代表64位, w代表32位 执行一个函数,结果放在x0位置也就是第一个参数的位置

image.png 这就是编译器优化

对象内存的大小由什么决定:成员变量 class isa为8,其为结构体指针类型,objc_class继承自objc_object if(size<16) size =16 字节对齐算法 (X+WORD_MASK)& ~WORD_MASK 8字节对齐,取8的整数

  • alloc流程图

image.png

一个自定义类alloc的过程:

通过调用objc_alloc->callAlloc,在callAlloc内部分有缓存无缓存两种情况,

(1)当有缓存时:通过 _objc_rootAllocWithZone -> _class_createInstanceFromZone -> instanceSize -> calloc -> initInstanceIsa

(2)无缓存时:callAlloc内部通过objc_msgSend 调用alloc方法, 在alloc方法内部执行 _objc_rootAlloc -> callAlloc,后面步骤与上相同。