autorelease 理解

前言: 自动变量,在计算机编程中, 是一个局部变量,当程序流进入并离开变量的范围时,该变量自动分配和释放.点击查看详细解释 , 由此引出这篇文章的主角 autorelease.

autorelease

解释: 类似于C语言中的自动变量, 超出其作用域(有效范围)便自动废弃

{
   int a;
}
// 变量 a 被废弃
 
 
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

不同于 C语言自动变量的是 在Objective-C中可以设定变量的作用域, 具体方法如下: 
- 生成并持有NSAutoreleasePool 
- 调用autorelease方法 
- 废弃 NSAutoreleasePool对象

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    id object = [[NSObject alloc] init];
    [object autorelease];
    NSLog(@"object ===== %@", object); // 正常
    [pool drain];
    [object class]; // crash
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

而实际在MRC下开发, 没有特殊要求可以不使用NSAutoreleasePool 因为在Cocoa框架中, 程序主循环NSRunLoop或者程序可运行的地方, 对这个对象(NSAutoreleasePool)的生成, 持有, 废弃, 已经进行了处理.

值得注意的是有时候不得不用, 比如 程序主循环未退出, 而生成了大量的autorelease对象, 那就会造成内存不足的现象. 所以适当使用

实际开发中不”明显”的autorelease 同样值得注意.

    NSMutableArray *array = [NSMutableArray arrayWithCapacity:1]; // 实际上这个方法也返回了一个autorelease对象.
 
 
  • 1
  • 1

伪代码arrayWithCapacity

- (id)arrayWithCapacity:(NSUInteger)num {
    NSMutableArray *obj = [[NSMutableArray alloc] init];
    [obj autorelease]; // 这里使用了autorelease
    return obj;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

autorelease如何实现

autoreleasepool 是没有单独的内存结构的,它是通过以 AutoreleasePoolPage 为结点的双向链表来实现的,在 runtime/NSObject.mm 581行可以找到相应的实现.

    id *add(id obj)
    {
        // 将对象加到内部数组中
    }

    void releaseAll() 
    {
        // 调用内部数组中的对象的release实例方法 
    }
    static inline id autorelease(id obj)
    {
        // 取得正在使用的 AutoreleasePoolPage 实例
    }
    static inline void *push() 
    {
         // 相当于生成或持有 NSAutoreleasePool类对象
    }

    static inline void pop(void *token) 
    {
        // 相当于废弃NSAutoreleasePool 类对象
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

引用: 
- 每一个线程的 autoreleasepool 其实就是一个指针的堆栈; 
- 每一个指针代表一个需要 release 的对象或者 POOL_SENTINEL(哨兵对象,代表一个 autoreleasepool 的边界); 
- 一个 pool token 就是这个 pool 所对应的 POOL_SENTINEL 的内存地址。当这个 pool 被 pop 的时候,所有内存地址在 pool token 之后的对象都会被 release ; 
- 这个堆栈被划分成了一个以 page 为结点的双向链表。pages 会在必要的时候动态地增加或删除; 
- Thread-local storage(线程局部存储)指向 hot page ,即最新添加的 autoreleased 对象所在的那个 page 。

文章参照

NSObject.mm

Objective-C Autorelease Pool 的实现原理

总结

对于iOS内存管理有了更深入的理解, 未完待续吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值