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

通过对《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
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值