alloc & init & dealloc

时间:2022-01-29 13:03:55

  在Objective-C中,alloc,init和dealloc是经常使用的函数,那么它们内部到底是如何实现的呢?通过查看libobjc运行时库,可以发现他们的工作原理。

  1 alloc

  alloc的功能就是为对象分配内存,关键代码如下:

if (!UseGC  &&  !zone  &&  fast) {
obj = (id)calloc(, size);
if (!obj) return nil;
obj->initInstanceIsa(cls, hasCxxDtor);
}

  在上面的代码中,calloc就是用来位对象分配内存的,并且calloc还会将这块内存区域初始化位0,其中的size就是对象的大小=isa指针(下面介绍) + 对象中的实例变量。为了内存对齐,size的大小可能会包含一些填充字节。分配好的内存被转换为id类型,下面是运行时库中对id类型的定义:

typedef struct objc_object *id;

  可以看到,id类型其实就是一个结构体指针,该结构体为objc_object,而struct objc_object的定义为(只展示了struct里面的实例变量,去掉了struct里面的方法):

struct objc_object {
private:
isa_t isa;
}

  struct objc_object中的成员变量isa是一个指针,指向的是对象所属类的Class对象。

  分配好内存之后,调用obj->initInstanceIsa方法,这个方法的作用就是用该对象所属类的Class对象地址初始化对象的isa指针,类的Class对象地址由参数cls提供。有关对象,对象所属类的Class对象的介绍,可以参看链接:刨根问底Objective-C Runtime(2)- Object & Class & Meta Class

  

  2 init

  init方法很简单,什么也不做,简单的返回对象地址,源码如下:

- (id)init {
return _objc_rootInit(self);
} id
_objc_rootInit(id obj)
{
// In practice, it will be hard to rely on this function.
// Many classes do not properly chain -init calls.
return obj;
}

  3 dealloc

  dealloc的作用就是释放内存,关键源代码如下:

id
object_dispose(id obj)
{
if (!obj) return nil; objc_destructInstance(obj); #if SUPPORT_GC
if (UseGC) {
auto_zone_retain(gc_zone, obj); // gc free expects rc==1
}
#endif free(obj); return nil;
}

  object_dispose是dealloc用来释放内存所调用的函数,可以看到,object_dispose只是简单的调用了free函数来释放内存。但是在调用free之前,object_dispose调用了objc_destructInstance。objc_destructInstance函数如下:

void *objc_destructInstance(id obj)
{
if (obj) {
// Read all of the flags at once for performance.
bool cxx = obj->hasCxxDtor();
bool assoc = !UseGC && obj->hasAssociatedObjects();
bool dealloc = !UseGC; // This order is important.
if (cxx) object_cxxDestruct(obj);
if (assoc) _object_remove_assocations(obj);
if (dealloc) obj->clearDeallocating();
} return obj;
}

其中标红色的方法会对类中包含的成员变量进行释放,这个释放动作是由编译器来保证的(ARC下),即使overwrite了某个类的dealloc,并且overwrite dealloc时没有对成员变量赋值nil,这个过程也不受影响,照样进行。

最后附上libObjc的下载连接:https://github.com/longv2go/objc4-646