您的位置:首页 > 其它

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

2015-08-31 09:24 295 查看
通过对《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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: