Objective-C內(nèi)存管理教程和原理剖析(四)
系統(tǒng)自動(dòng)創(chuàng)建新的autorelease pool
在生成新的Run Loop的時(shí)候,系統(tǒng)會(huì)自動(dòng)創(chuàng)建新的autorelease pool(非常感謝網(wǎng)友hhyytt和neogui的提醒)。注意,此處不同于xcode在新建項(xiàng)目時(shí)自動(dòng)生成的代碼中加入的autorelease pool,xcode生成的代碼可以被刪除,但系統(tǒng)自動(dòng)創(chuàng)建的新的autorelease pool是無法刪除的(對(duì)于無Garbage Collection的環(huán)境來說)。Objective-C沒有給出實(shí)現(xiàn)代碼,官方文檔也沒有說明,但我們可以通過小程序來證明。
在這個(gè)小程序中,我們先生成了一個(gè)autorelease pool,然后生成一個(gè)autorelease的ClassA的實(shí)例,再在一個(gè)新的run loop中生成一個(gè)autorelease的ClassB的對(duì)象(注意,我們并沒有手動(dòng)在新run loop中生成autorelease pool)。精簡的示例代碼如下,詳細(xì)代碼請(qǐng)見附件中的memman-run-loop-with-pool.m。
- int main(int argc, char**argv)
- {
- NSLog(@"create an autorelasePool\n");
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- NSLog(@"create an instance of ClassA and autorelease\n");
- ClassA *obj1 = [[[ClassA alloc] init] autorelease];
- NSDate *now = [[NSDate alloc] init];
- NSTimer *timer = [[NSTimer alloc] initWithFireDate:now
- interval:0.0
- target:obj1
- selector:@selector(createClassB)
- userInfo:nil
- repeats:NO];
- NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
- [runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
- [timer release];
- [now release];
- [runLoop run]; //在新loop中調(diào)用一函數(shù),生成ClassB的autorelease實(shí)例
- NSLog(@"releasing autorelasePool\n");
- [pool release];
- NSLog(@"autorelasePool is released\n");
- return 0;
- }
輸出如下:
create an autorelasePool
create an instance of ClassA and autorelease
create an instance of ClassB and autorelease
ClassB destroyed
releasing autorelasePool
ClassA destroyed
autorelasePool is released
注意在我們銷毀autorelease pool之前,ClassB的autorelease實(shí)例就已經(jīng)被銷毀了。
有人可能會(huì)說,這并不能說明新的run loop自動(dòng)生成了一個(gè)新的autorelease pool,說不定還只是用了老的autorelease pool,只不過后來drain了一次而已。我們可以在main函數(shù)中不生成autorelease pool。精簡的示例代碼如下,詳細(xì)代碼請(qǐng)見附件中的memman-run-loop-without-pool.m。
- int main(int argc, char**argv)
- {
- NSLog(@"No autorelasePool created\n");
- NSLog(@"create an instance of ClassA\n");
- ClassA *obj1 = [[ClassA alloc] init];
- NSDate *now = [[NSDate alloc] init];
- NSTimer *timer = [[NSTimer alloc] initWithFireDate:now
- interval:0.0
- target:obj1
- selector:@selector(createClassB)
- userInfo:nil
- repeats:NO];
- NSRunloop *runLoop = [NSRunLoop currentRunLoop];
- [runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
- [timer release];
- [now release];
- [runLoop run]; //在新loop中調(diào)用一函數(shù),生成ClassB的autorelease實(shí)例
- NSLog(@"Manually release the instance of ClassA\n");
- [obj1 release];
- return 0;
- }
輸出如下:
No autorelasePool created
create an instance of ClassA
create an instance of ClassB and autorelease
ClassB destroyed
Manually release the instance of ClassA
ClassA destroyed
我們可以看出來,我們并沒有創(chuàng)建任何autorelease pool,可是ClassB的實(shí)例依然被自動(dòng)銷毀了,這說明新的run loop自動(dòng)創(chuàng)建了一個(gè)autorelease pool,這個(gè)pool在新的run loop結(jié)束的時(shí)候會(huì)銷毀自己(并自動(dòng)release所包含的對(duì)象)。
補(bǔ)充說明
在研究retain count的時(shí)候,我不建議用NSString。因?yàn)樵谙旅娴恼Z句中,
- NSString *str1 = @”constant string”;
str1的retain count是個(gè)很大的數(shù)字。Objective-C對(duì)常量字符串做了特殊處理。
當(dāng)然,如果你這樣創(chuàng)建NSString,得到的retain count依然為1
- NSString *str2 = [NSString stringWithFormat:@”123”];
示例代碼文件鏈接:http://files.cnblogs.com/VinceYuan/objective-c-memman.zip