引言
在实际iOS开发中我,我们经常会调用alloc
方法,然而对于alloc
方法的底层实现原理,大部分人并不是很清楚。
一、准备工作
1、探究底层,肯定要阅读苹果源码。源码库的下载地址:opensource或者 Source Browser, 两者的区别
在于Source Browser
里面的版本更新更快更详细
,搜索objc4
即得到我们索要下载的源码。


2.源码编译:这里暂不讨论,有兴趣的可以自己百度查资料,这里推荐cooci大神
的github地址:https://github.com/LGCooci?tab=repositories,里面有各种版本的更新和步骤。
二、alloc流程图结果
如下:

那么,究竟上面的流程图
是怎样出来的呢?我们都知道,正常情况项目里面的这些方法名我们是不知道的,那么,探究
流程图的思路
是什么,需要具备哪方面
的知识?
三、alloc流程图探索过程
(1)首先我们需要了解一个概念:符号断点
。在我们对底层alloc
源码一无所知
的情况下,我们只知道创建对象要alloc
,我们就已alloc
方法为突破口
。

这里需要注意的是,需要
先进入
到你想要看
的断点,再把符号断点
打开,切记切记
。点step into
键的时候需要同时按住control键
。

在这里可以发现代码进入了objc_alloc
,继续点击step into
还会进入一些底层的其它方法,这里不做详细介绍。
(2)通过反汇编调试


还是先运行到断点处
,再打开汇编,继续点击step into+control键
可以从汇编里面看出,走了objc_alloc
方法。
(3)看源码,是最直观
的方法,推荐大家使用。

核心代码:
static ALWAYS_INLINE id _class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone,
int construct_flags = OBJECT_CONSTRUCT_NONE,
bool cxxConstruct = true,
size_t *outAllocatedSize = nil)
{
ASSERT(cls->isRealized());
// Read class's info bits all at once for performance
bool hasCxxCtor = cxxConstruct && cls->hasCxxCtor();
bool hasCxxDtor = cls->hasCxxDtor();
bool fast = cls->canAllocNonpointer();
size_t size;
//先计算内存空间所需要的大小,在这个过程中遵循着内存对齐规则,以8字节为单位,因为我们的基本数据类型是不会超过8个字节的,最主要地是,以空间换时间,让cpu保持高效。
size = cls->instanceSize(extraBytes);
if (outAllocatedSize) *outAllocatedSize = size;
id obj;
//alloc:向栈申请开辟内存,返回地址指针
if (zone) {
obj = (id)malloc_zone_calloc((malloc_zone_t *)zone, 1, size);
} else {
obj = (id)calloc(1, size);
}
if (slowpath(!obj)) {
if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {
return _objc_callBadAllocHandler(cls);
}
return nil;
}
if (!zone && fast) {
//将申请的内存地址指针和isa指针即我们的类绑定起来
obj->initInstanceIsa(cls, hasCxxDtor);
} else {
// Use raw pointer isa on the assumption that they might be
// doing something weird with the zone or RR.
obj->initIsa(cls);
}
if (fastpath(!hasCxxCtor)) {
return obj;
}
construct_flags |= OBJECT_CONSTRUCT_FREE_ONFAILURE;
return object_cxxConstructFromClass(obj, cls, construct_flags);
}
网友评论