OC_自动释放池autoreleasepool

序言:翻阅资料,学习,探究,总结,借鉴,谢谢探路者,我只是个搬运工。
参考、转发资料:
http://draveness.me/autoreleasepool/

1. 自动释放池autoreleasepool介绍

自动释放池储于内存中的栈中遵循"先进后出"原则。autoreleasepool就是一个容器,盛放添加到其中的变量。存在的两种形式,一种是在项目创建时中的main.m文件就有一个,即程序运行开始就帮我们创建了最外层,也是最大的一个自动释放池。另一种就是根据我们自己的需求自己创建了。而其作用就是自动释放池释放的时候帮助我们释放一些存储在释放池中的内存变量,降低整个程序在运行过程中内存消耗过大。

2. autoreleasepool内部结构的分析。

  1. autoreleasepool 就是一个结构体的变量。
    autoreleasepool是 __AtAutoreleasePool 结构体的一个变量。
struct __AtAutoreleasePool {  
  __AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();}
  ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}
  void * atautoreleasepoolobj;
};

这个结构体会在初始化时调用 objc_autoreleasePoolPush() 方法,会在析构时调用 objc_autoreleasePoolPop 方法。
这表明,我们的 main 函数在实际工作时其实是这样的:

int main(int argc, const char * argv[]) {
    {
        void * atautoreleasepoolobj = objc_autoreleasePoolPush();
        
        // do whatever you want
        
        objc_autoreleasePoolPop(atautoreleasepoolobj);
    }
    return 0;
}
  1. 分析方法 objc_autoreleasePoolPush 和 objc_autoreleasePoolPop 的实现
void *objc_autoreleasePoolPush(void) {
      return AutoreleasePoolPage::push();
}
void objc_autoreleasePoolPop(void *ctxt) {
      AutoreleasePoolPage::pop(ctxt);
}
  1. AutoreleasePoolPage 的结构
class AutoreleasePoolPage {  
    magic_t const magic;
    id *next;
    pthread_t const thread;
    AutoreleasePoolPage * const parent;
    AutoreleasePoolPage *child;
    uint32_t const depth;
    uint32_t hiwat;
};
- magic 用于对当前 AutoreleasePoolPage 完整性的校验
- thread 保存了当前页所在的线程
  1. 自动释放池中的 AutoreleasePoolPage 是以双向链表的形式连接起来的:
    parent 和 child 就是用来构造双向链表的指针。

    AutoreleasePoolPage的双向链表.png

  2. 自动释放池中的栈
    如果我们的一个 AutoreleasePoolPage 被初始化在内存的 0x100816000 ~ 0x100817000 中,它在内存中的结构如下:


    栈中内存存储.png

    从0x100816038 ~ 0x100817000 都是用来存储加入到自动释放池中的对象。begin() 和 end() 这两个类的实例方法帮助我们快速获取 0x100816038 ~ 0x100817000 这一范围的边界地址。

next 指向了下一个为空的内存地址,如果 next 指向的地址加入一个 object,它就会如下图所示移动到下一个为空的内存地址中:


自动释放池中变量的存储过程.png
  1. POOL_SENTINEL(哨兵对象)这是个非常重要的变量
    POOL_SENTINEL 只是 nil 的别名,它是用来记录位置的。记录每个新的自动释放池存储位置的开始。模块化的划分每个自动释放池中存储的变量。
    回顾最开始的知识点
int main(int argc, const char * argv[]) {  
    {
        void * atautoreleasepoolobj = objc_autoreleasePoolPush();

        // do whatever you want

        objc_autoreleasePoolPop(atautoreleasepoolobj);
    }
    return 0;
}

上面的 atautoreleasepoolobj 就是一个 POOL_SENTINEL。告诉我们记录这个自动释放池的开始位置。

当方法 objc_autoreleasePoolPop 调用时,就会向自动释放池中的对象发送 release 消息,直到第一个 POOL_SENTINEL:


自动释放池的释放过程.png
  1. 释放自动释放池
  • 使用 pageForPointer 获取当前所在的 AutoreleasePoolPage
  • 调用 releaseUntil 方法释放栈中的对象,直到当前页数中的最后一个
  • 调用 child 的 kill 方法,将当前页面以及子页面全部删除

3. 总结

  • 自动释放池是存储在栈中,那加入到自动释放池的变量也在栈中存储一份指向变量的指针地址,变量在自动释放池当中的存储是从低地址指向高地址。当前自动释放池释放了,那么这些变量才会从内存当中释放。
  • 在自动释放池的结构中POOL_SENTINEL(哨兵对象)记录你的位置,区分每个自动释放池的开始位置,以便于区分多层次释放的某一个自动释放池。
  • 当方法 objc_autoreleasePoolPop 调用时,就会向自动释放池中的对象发送 release 消息,直到第一个 POOL_SENTINEL,此时最里层的自动释放池将得到释放,遵循入栈的形式,先进后出。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容