OS X内存管理:从源码进行分析(一)

来源:互联网 发布:行知幼稚园 编辑:程序博客网 时间:2024/06/06 05:47

通过对《Objective-C高级编程》的学习,就来总结一下。

在Objective-C中的内存管理中,autorelease就是自动释放,看上去很像ARC对不对?但是呢,却并不是,其实有点像我们曾经在学习C语言中的局部变量

GNUstep的实现

就下来就详细的总结一下autorelease的实现原理。由于NSObject类的Foundation框架并没有被开源,所以我们就研究一下GNUstep这个开源软件。

首先看一个源代码

[obj autorelease]

这个源代码实际是调用了 NSObject类的autorelease方法。

-(id)autorelease{    [NSAutoreleasePool addObject:self];}

从以上这个代码中我们就可以分析出来,其实autorelease实际上就是调用了NSAutoreleasePool中的addObject方法

看到了以上的内容,我们就需要详细的探讨一下NSAutoreleasePool的实现原理。以下是我摘要的源代码,因为NSAutoreleasePool的源代码的实现太复杂了,所以这里的源代码是经过简化后的

NSAutoreleasePool.m addObject

+(void)addObject:(id)anObj{    NSAutoreleasePool *pool = 取得我们正在运用的NSAutoreleasePool;    if(pool!=nil){        [pool addObject: anObj];    } else {        NSLog(@"NSAutoreleasePool对象不存在");    }}

addObject 类方法调用正在使用的NSAutoreleasePool对象的addObject,这句话可能会有一些难理解,没关系,接着看一组源代码。

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];id obj = [[NSObject alloc] init];[obj autorelease];

通过上面的代码我们就可以看出,被赋予pool变量,那么就是正在使用NSAutoreleasePool的实例化对象。

在我自己学习的过程中,还看到另外一种嵌套的方式

NSAutoreleasePool *pool0 = [[NSAutoreleasePool alloc] init];    NSAutoreleasePool *pool1 = [[NSAutoreleasePool alloc] init];        NSAutoreleasePool *pool2 = [[NSAutoreleasePool alloc] init];        id obj = [[NSObject alloc] init];        [obj autorelease];        [pool2 drain];    [pool1 drain];[pool0 drain];

在这种嵌套结构中,pool2为NSAutoreleasePool的使用对象,遵循使用最内测的对象想这个原则。

看一下addObject的实现原理。其实就是调用了array的addObject方法

-(void)addObject :(id)anObj{    [array addObject : anObj];}

以上就是GNUstep实现,其实GNUstep使用的就是连接列表,这跟NSNutableArray对象的中追加的原理是一样的,就是说如果我们调用了autorelease方法,这个调用autorelease方法的对象就会被追加到NSAutoreleasePool的数组中

[pool drain];

通过drain就可以删除正在使用NSAutoreleasePool的对象

看一下drain的实现原理

-(void)drain{    for(id obj in array){        [obj release];    }    [array release];}

通过每次的循环都在调用release方法来实现释放。

苹果的实现

以下为objc4库中的autorelease实现原理

class AutoreleasePoolPage{    static inline void *push()    {        //在这里进行NSAutoreleasePool的生成    }    static inline void *pop()    {        //废弃掉NSAutoreleasePool类对象        releaseAll();    }    static inline id autorelease(id obj)    {        //这里就相当于NSAutoreleasePool类的addObject方法        AutoreleasePoolPage * autoreleasePoolPage = 取得正在使用AutoreleasePoolPage类的对象;        autoreleasePoolPage->add(obj);    }    id *add(id obj)    {        //讲对象追加到数组中    }    void releaseAll()    {        //调用release实例    }}void *obj_ autoreleasePoolPush(void){    return autoreleasePoolPage::push();}void *obj_ autoreleasePoolPop(void){    return autoreleasePoolPage::pop(void *ctxt);}void *obj_ autorelease(id obj){    return autoreleasePoolPage::autorelease(obj);}c++中虽然有类似NSNutableArray的动态数组,但是行为却和GNUstep的实现完全不同。

首先先来看一下NSAutoreleasePool类方法和autorelease方法的运行过程。以及和从从从c++的对象关系

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];//相当于obj_ autoreleasePoolPush()id obj = [[NSObject alloc] init];[obj autorelease];//相当于*obj_ autorelease(obj)[pool drain];//相当于*obj_ autoreleasePoolPop(pool)
2 0
原创粉丝点击