对象原理以及调试方法
2019-12-18 本文已影响0人
海浪萌物
当我们调试时候不知道一个系统方法后面干了些啥,调用了哪些动态库的时候,我们可以通过下断点方式进行调试,有三种方式
1、断点调试
在调用系统方法前加一个断点,然后按住control键,点击in键,也就是 image.png这个键,一步一步跳转就能看到该方法调用的顺序,例如 image.png
就能知道alloc调用了objc_alloc方法
2、下符号断点方式
在symbolic 里面symbol里面写入已知的系统方法,例如 image.png然后就会出现下面这种情况 image.png
说明拥有alloc系统方法的类很多, image.png
3、通过汇编 :
Debug ---> Debug workflow ----> allways show,然后在系统方法前加一个断点后,就会出现这种情况, image.png会把该方法的所有调用顺序都展现出来
二、alloc流程
我们查找下alloc的调用流程,授信我们从官网下载objc4-750的源码,通过搜索alloc {我们可以发现 image.pngalloc其实是调用_objc_rootAlloc函数,再搜索_objc_rootAlloc函数, image.png
会发现_objc_rootAlloc调用的是callAlloc方法,再搜索callAlloc函数 image.png
然后一步一步分析
然后查看calloc函数,
image.png
其中
calloc函数意思是开辟一个内存空间,
cls->bits.fastInstanceSize()意思是开辟一个cls类的内存空间的大小 前面__count意思是倍数,
其中cls->bits.fastInstanceSize()大小是遵循内存对齐原则开辟内存的,
内存对齐原则:
内存对⻬的原则:
1:数据成员对⻬规则:结构体(struct)(或联合体(union))的数据成员,第
一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要
从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,
结构体等)的整数倍开始(比如int为4字节,则要从4的整数倍地址开始存
储。
2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从
其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b
里有char,int ,double等元素,那b应该从8的整数倍开始存储.)
3:收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大
成员的整数倍.不足的要补⻬。
关于内存对齐原则
1、对象的属性需要的内存空间是8位倍数,如果不以8的倍数,CPU读起来很a耗性能高,所以以8字节为倍数,提高读取效率,以空间换时间
2、开辟的对象如果小于16的分配16个字节,防止越界,
由于calloc不在objc源码里面,是在malloc源码里面,我们下载malloc源码,查找下calloc的实现,
image.png
然后进入到 retval = malloc_zone_calloc(default_zone, num_items, size);
如果开辟不成功就会调用initInstanceIsa方法去
image.png 再分析这一块 image.png 首先查看class_createInstance函数的实现 image.png
然后再查看_class_createInstanceFromZone函数的实现
image.png
当满足条件时候
image.png 先给objc开辟一个内存空间,然后将类cls的isa指针给obj,我们查看下initInstanceIsa的实现 image.png
然后查看initIsa函数实现
image.png