OC 底层原理(1)-对象原理( 对象的创建)(随记)

521 阅读3分钟

一、alloc 探索---查找alloc源码所在位置

先给出一段代码
    LGPerson *p1 = [LGPerson alloc];
    LGPerson *p2 = [p1 init];
    LGPerson *p3 = [p1 init];
    LGNSLog(@"%@ - %p",p1,&p1);
    LGNSLog(@"%@ - %p",p1,&p2);
    LGNSLog(@"%@ - %p",p1,&p3);

打印结果:

<LGPerson: 0x6000016c6260> - 0x7ffee49c8178

<LGPerson: 0x6000016c6260> - 0x7ffee49c8170

<LGPerson: 0x6000016c6260> - 0x7ffee49c8168

从结果可以总结为,p1,p2,p3 指向同一个内存空间,但创建出来的三个对象的指针地址是不同的。

以此我们可能就会产生如下几个疑问:

1、为什么会出现这个打印结果呢?

因为 alloc 创建实例对象的同时也申请了一块内存空间,p1,p2,p3是分配的3个对象的指针,因此 p1,p2,p3 属于同一个对象并都指向这块内存空间。

2、alloc 又是怎么实现的呢?

我们通过分析alloc源码来寻找这个问题的答案,有如下三种方式来知道alloc源码所在的动态库,libobjc.A.dylib:

1)第一种方式:真机调试,打断点

在如图所示打上断点,然后按住 ‘control’的同时点击箭头所指的按钮进入,再继续点击此按钮,直到出现 libobjc.A.dylib

2)第二种方式:选择Symbolic Breakpoint ,在Symbol这栏输入 alloc 也能得到想要的答案。

然后出现很多很多实现了alloc方法的断点,再次真机运行

此时再点击上图箭头所指的按钮之后也会出现

3)第三种方法:通过汇编 选择->Debug->Debug Workflow -> Always Show Disassembly,再次在真机上运行,此时会直接跳转到汇编界面

在其中我们照样可以找到 objc_alloc,然后将断点下的此处,再按住 control 键,点击下图箭头所指按钮

一直按直到出现如下图所示,出现alloc所在的动态库名

3、创建对象的过程中与init的关系是什么呢?

由上图 init 的源码可看出,init什么也没做,只是提供了一个初始化方法,方便我们重写,由我们自己随意发挥,工厂设计的模式

由上图得出new跟 alloc->init 一样的效果

二、alloc探索---下载并配置alloc所在的动态库开源的源码(objc)

源码下载地址:opensource.apple.com/tarballs/

源码编译调试参考点击

三、alloc探索--分析查看 alloc 源码流程

1)alloc 流程图

部分源码解释

calloc : 申请对象和开辟内存空间

initInstanceIsa :关联内存指针

2)申请内存空间(字节对齐)

size:申请的内存空间大小,对象自带内存大小 8 字节(Class isa)

a.对象内存空间规则 8 字节对齐(目的:提高 cpu 读取速度,以空间换取时间)

b.内存所占空间小于16字节时,最少16字节,为了防止读取或存储时越界

查看内存空间结构:

由上图可知:栈点指针起始位置为isa

打印指令:

x [对象名] :查看对象的存储空间,以16进制打印内存空间

x/[n]xg [对象名] : 以16 进制读取 n 个内存段

register read :读寄存器

随记:

x0:是第一个参数的传递者,也是返回值存储的地方(isa)

iOS 属于小端模式,内存地址倒着读