autorelease&autoreleasePool

一、什么是 autorelease&autoreleasePool

  • 1、对象执行autorelease方法或者直接在autoreleasePool中创建对象,会将对象添加到autoreleasePool中,当自动释放池销毁的时候,会对所有对象做release操作
  • 2、ARC的规则:
    • alloc/new/copy/mutableCopy开头的方法(类方法和实例方法)返回的对象不是autorelease对象
    • init开头的方法(实例方法)返回的对象不是autorelease对象
  • 3、显示添加AutoreleasePool
    • 3.1、NSAutoreleasePool(只能在 MRC下使用)
    • 3.2、@autoreleasePool{}(ARC和 MRC均适用)
    • 3.3、显示调用@autoreleasePool{},只有是autorelease对象才会立刻释放;不是autorelease对象添加或不添加没有什么用,都会立刻释放;自动释放池起到一个延迟释放的作用。

1、代码一

- (void)dealloc
{
    NSLog(@"LGMan dealloc");
}
+ (instancetype)object{
    return [[LGMan alloc] init];
}
实例一、不会发送autorelease方法,不会注册到自动释放池当中;alloc/init/new/copy/mutableCopy开头的方法返回的对象不是autorelease对象,所以会在出了作用域就直接释放了
    __weak id tmp = nil;
    {
        LGMan *man = [[LGMan alloc] init];
        tmp = man;
    }
    NSLog(@"tmp == %@",tmp);

2019-09-17 10:27:13.073186+0800 LGAutoRelaseTest[10073:2217243] LGMan dealloc
2019-09-17 10:27:13.073317+0800 LGAutoRelaseTest[10073:2217243] tmp == (null)
实例二、发送autorelease方法,注册到自动释放池当中;autorelease对象,会在自动释放池销毁的时候释放
    __weak id tmp = nil;
    {
        LGMan *man = [LGMan object];
        tmp = man;
    }
    NSLog(@"tmp == %@",tmp);

2019-09-17 10:32:16.558413+0800 LGAutoRelaseTest[10142:2239041] tmp == <LGMan: 0x6000003942b0>
2019-09-17 10:32:16.560429+0800 LGAutoRelaseTest[10142:2239041] LGMan dealloc
实例三、MRC下手动发送autorelease,就算不是autorelease对象 也会加入到自动释放池当中
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        __weak id tmp = nil;
        {
            NSObject *man = [[NSObject alloc] autorelease];//MRC,手动发送autorelease,会加入到自动释放池。打印 tmp == <NSObject: 0x100614480>
//            NSObject *man =  [NSObject alloc];//ARC,因为不是autorelease对象,所以不会自动发送autorelease,所以不会加入到自动释放池。打印 tmp == (null)
            tmp = man;
        }
        NSLog(@"tmp == %@",tmp);
    }
    return 0;
}
实例四、{} 作用域
    __weak id tmp = nil;
    LGMan *man = [LGMan object];
    tmp = man;
    NSLog(@"tmp == %@",tmp);

2019-09-17 10:38:53.335993+0800 LGAutoRelaseTest[10242:2269366] tmp == <LGMan: 0x600002514530>
2019-09-17 10:38:53.337869+0800 LGAutoRelaseTest[10242:2269366] LGMan dealloc

    __weak id tmp = nil;
    LGMan *man = [[LGMan alloc] init];
    tmp = man;
    NSLog(@"tmp == %@",tmp);

2019-09-17 10:41:58.412400+0800 LGAutoRelaseTest[10283:2281480] tmp == <LGMan: 0x600002c27df0>
2019-09-17 10:41:58.412501+0800 LGAutoRelaseTest[10283:2281480] LGMan dealloc

2、代码二

+ (NSString *)allocLGString{
//    return [[NSString alloc] initWithString:@"HelloLGLGLG"];
//    return @"HelloLGLGLG";
    
    // 不会帮我们插入autorelease方法
//    return [NSString stringWithFormat:@"HelloLGLGLG"];

    // "Hello" Taggpointer,返回不能称之为对象,只有长度大于10的时候,返回才能称之为对象
    // initWithCString这个方法会帮我们插入autorelease方法
//    return [[NSString alloc] initWithCString:"Hello" encoding:NSUTF8StringEncoding];
    return [[NSString alloc] initWithCString:"HelloHello" encoding:NSUTF8StringEncoding];
}

+ (NSString *)newLGString{
    return [[NSString alloc] initWithCString:"HelloHello" encoding:NSUTF8StringEncoding];
}

+ (NSString *)copyLGString{
    return [[NSString alloc] initWithCString:"HelloHello" encoding:NSUTF8StringEncoding];
}

+ (NSString *)initLGString{
    return [[NSString alloc] initWithCString:"HelloHello" encoding:NSUTF8StringEncoding];
}
+ (NSString *)helloLGString{
    return [[NSString alloc] initWithCString:"HelloHello" encoding:NSUTF8StringEncoding];
}
+ (NSString *)createLGString{
    return [[NSString alloc] initWithCString:"HelloHello" encoding:NSUTF8StringEncoding];
}
    @autoreleasepool {
        //nil  autorelease
        __weak NSString *tmp1 = [LGMan allocLGString];
        __weak NSString *tmp2 = [LGMan newLGString];
        __weak NSString *tmp3 = [LGMan copyLGString];
        NSLog(@"%@",tmp1);
        NSLog(@"%@",tmp2);
        NSLog(@"%@",tmp3);
        
        //hello world  autorelease , 自动释放池当中!!!
        __weak NSString *tmp4 = [LGMan initLGString];
        __weak NSString *tmp5 = [LGMan createLGString];
        __weak NSString *tmp6= [LGMan helloLGString];
        NSLog(@"%@",tmp4);
        NSLog(@"%@",tmp5);
        NSLog(@"%@",tmp6);
    }

2019-09-17 11:23:35.038652+0800 LGAutoRelaseTest[10913:2426586] (null)
2019-09-17 11:23:35.038770+0800 LGAutoRelaseTest[10913:2426586] (null)
2019-09-17 11:23:35.038853+0800 LGAutoRelaseTest[10913:2426586] (null)
2019-09-17 11:23:35.038952+0800 LGAutoRelaseTest[10913:2426586] HelloHello
2019-09-17 11:23:35.039029+0800 LGAutoRelaseTest[10913:2426586] HelloHello
2019-09-17 11:23:35.039134+0800 LGAutoRelaseTest[10913:2426586] HelloHello

3、代码三

显示添加AutoreleasePool
    @autoreleasepool {
        //LLVM autorelease
        id object = [[NSObject alloc] init];
    }
    //1、生成一个 NSAutoreleasePool 对象
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    //2、调用 Autorelease 方法
    id object = [[NSObject alloc] init];
    [object autorelease];
    //3、废弃 NSAutoreleasePool 对象
    [pool drain]; //object relase消息

显示调用autoreleasepool 对照实例二输出结果

    __weak id tmp = nil;
    @autoreleasepool {
        LGMan *man = [LGMan object];
        tmp = man;
    }
    NSLog(@"tmp == %@",tmp);

2019-09-17 12:13:19.639192+0800 LGAutoRelaseTest[11431:2536940] LGMan dealloc
2019-09-17 12:13:19.639332+0800 LGAutoRelaseTest[11431:2536940] tmp == (null)

二、打印:_objc_autoreleasePoolPrint()

#import <Foundation/Foundation.h>
extern void _objc_autoreleasePoolPrint(void);

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        for (int i = 0; i < 5; i++) {
            NSObject *objc = [[NSObject alloc] autorelease];
        }
        _objc_autoreleasePoolPrint();
        
    }
    return 0;
}

0x101003000 -> 0x101003038: 3*16+8 = 56

objc[45587]: ##############
objc[45587]: AUTORELEASE POOLS for thread 0x1000d1dc0
objc[45587]: 6 releases pending.
objc[45587]: [0x101003000]  ................  PAGE  (hot) (cold)
objc[45587]: [0x101003038]  ################  POOL 0x101003038
objc[45587]: [0x101003040]       0x100619300  NSObject
objc[45587]: [0x101003048]       0x1007026b0  NSObject
objc[45587]: [0x101003050]       0x100702da0  NSObject
objc[45587]: [0x101003058]       0x100701d80  NSObject
objc[45587]: [0x101003060]       0x101b01ec0  NSObject
objc[45587]: ##############
Program ended with exit code: 0

16 + 8 + 8 + 8 + 8 + 4 + 4 = 56

class AutoreleasePoolPage : private AutoreleasePoolPageData(结构体)

  • magic 用来校验 AutoreleasePoolPage 的结构是否完整;
  • next 指向最新添加的 autoreleased 对象的下一个位置,初始化时指向begin() ;
  • thread 指向当前线程;
  • parent 指向父结点,第一个结点的 parent 值为 nil ;
  • child 指向子结点,最后一个结点的 child 值为 nil ;
  • depth 代表深度,从 0 开始,往后递增 1;
  • hiwat 代表 high water mark 最大入栈数量标记

(4096-56) / 8 = 505

i < 505时,开始出现满页了,1+504+1
i < 505+505时,1+504+505+1
每一页的大小时505,由于第一页有边界(哨兵),所以第一页最多放504个8字节对象,之后的每一页最多放505个8字节对象。

#import <Foundation/Foundation.h>
extern void _objc_autoreleasePoolPrint(void);

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        for (int i = 0; i < 505; i++) {
            NSObject *objc = [[NSObject alloc] autorelease];
        }
        _objc_autoreleasePoolPrint();
        
    }
    return 0;
}
objc[45730]: ##############
objc[45730]: AUTORELEASE POOLS for thread 0x1000d1dc0
objc[45730]: 506 releases pending.
objc[45730]: [0x101003000]  ................  PAGE (full)  (cold)
objc[45730]: [0x101003038]  ################  POOL 0x101003038
objc[45730]: [0x101003040]       0x100622110  NSObject
objc[45730]: [0x101003048]       0x100622f00  NSObject
objc[45730]: [0x101003050]       0x1006222e0  NSObject
.
.
.
objc[45730]: [0x101003fe8]       0x10062c8f0  NSObject
objc[45730]: [0x101003ff0]       0x10062c900  NSObject
objc[45730]: [0x101003ff8]       0x10062c910  NSObject
objc[45730]: [0x101001000]  ................  PAGE  (hot) 
objc[45730]: [0x101001038]       0x10062c920  NSObject
objc[45730]: ##############

三、@autoreleasepool与线程,@autoreleasepool嵌套

#import <Foundation/Foundation.h>
extern void _objc_autoreleasePoolPrint(void);

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        NSObject *objc = [[NSObject alloc] autorelease];
        NSLog(@"*****%@",objc);
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            
//           NSObject *objc = [[NSObject alloc] autorelease];
//           NSLog(@"-----:%@",objc);
//           _objc_autoreleasePoolPrint();
            
            /**
             1,@autoreleasepool 与线程关联
             2,@autoreleasepool 嵌套,只会创建一个page,但是两个哨兵
             */
            @autoreleasepool {
                NSObject *objc = [[NSObject alloc] autorelease];
                NSLog(@"-----:%@",objc);
                _objc_autoreleasePoolPrint();
            }
        });
        _objc_autoreleasePoolPrint();
        
        sleep(3);
        
    }
    return 0;
}

1,@autoreleasepool 与线程关联

NSObject *objc = [[NSObject alloc] autorelease];
NSLog(@"-----:%@",objc);
 _objc_autoreleasePoolPrint();

2020-03-23 18:13:22.773330+0800 ClangTest[46295:1287347] *****<NSObject: 0x100537f10>
objc[46295]: ##############
objc[46295]: AUTORELEASE POOLS for thread 0x1000d2dc0
objc[46295]: 2 releases pending.
objc[46295]: [0x100805000]  ................  PAGE  (hot) (cold)
objc[46295]: [0x100805038]  ################  POOL 0x100805038
objc[46295]: [0x100805040]       0x100537f10  NSObject
2020-03-23 18:13:22.774101+0800 ClangTest[46295:1287749] -----:<NSObject: 0x103200000>
objc[46295]: ##############
objc[46295]: ##############
objc[46295]: AUTORELEASE POOLS for thread 0x70000ec1d000
objc[46295]: 2 releases pending.
objc[46295]: [0x103800000]  ................  PAGE  (hot) (cold)
objc[46295]: [0x103800038]  ################  POOL 0x103800038
objc[46295]: [0x103800040]       0x103200000  NSObject
objc[46295]: ##############
Program ended with exit code: 0

2,@autoreleasepool 嵌套,只会创建一个page(page的创建是来源于线程的),但是两个哨兵(哨兵的创建是来源于作用域空间)

@autoreleasepool {
        NSObject *objc = [[NSObject alloc] autorelease];
        NSLog(@"-----:%@",objc);
         _objc_autoreleasePoolPrint();
 }

2020-03-23 17:59:07.337042+0800 ClangTest[46239:1280138] *****<NSObject: 0x1006abba0>
objc[46239]: ##############
objc[46239]: AUTORELEASE POOLS for thread 0x1000d2dc0
objc[46239]: 2 releases pending.
objc[46239]: [0x10200c000]  ................  PAGE  (hot) (cold)
2020-03-23 17:59:07.337869+0800 ClangTest[46239:1280172] -----:<NSObject: 0x103100040>
objc[46239]: [0x10200c038]  ################  POOL 0x10200c038
objc[46239]: [0x10200c040]       0x1006abba0  NSObject
objc[46239]: ##############
objc[46239]: ##############
objc[46239]: AUTORELEASE POOLS for thread 0x70000c8dc000
objc[46239]: 3 releases pending.
objc[46239]: [0x103800000]  ................  PAGE  (hot) (cold)
objc[46239]: [0x103800038]  ################  POOL 0x103800038
objc[46239]: [0x103800040]  ################  POOL 0x103800040
objc[46239]: [0x103800048]       0x103100040  NSObject
objc[46239]: ##############
Program ended with exit code: 0
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,639评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,093评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,079评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,329评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,343评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,047评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,645评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,565评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,095评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,201评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,338评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,014评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,701评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,194评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,320评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,685评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,345评论 2 358

推荐阅读更多精彩内容