Objective-C內(nèi)存管理教程和原理剖析(四)
系統(tǒng)自動創(chuàng)建新的autorelease pool
在生成新的Run Loop的時候,系統(tǒng)會自動創(chuàng)建新的autorelease pool(非常感謝網(wǎng)友hhyytt和neogui的提醒)。注意,此處不同于xcode在新建項目時自動生成的代碼中加入的autorelease pool,xcode生成的代碼可以被刪除,但系統(tǒng)自動創(chuàng)建的新的autorelease pool是無法刪除的(對于無Garbage Collection的環(huán)境來說)。Objective-C沒有給出實現(xiàn)代碼,官方文檔也沒有說明,但我們可以通過小程序來證明。
在這個小程序中,我們先生成了一個autorelease pool,然后生成一個autorelease的ClassA的實例,再在一個新的run loop中生成一個autorelease的ClassB的對象(注意,我們并沒有手動在新run loop中生成autorelease pool)。精簡的示例代碼如下,詳細(xì)代碼請見附件中的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實例
- 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實例就已經(jīng)被銷毀了。
有人可能會說,這并不能說明新的run loop自動生成了一個新的autorelease pool,說不定還只是用了老的autorelease pool,只不過后來drain了一次而已。我們可以在main函數(shù)中不生成autorelease pool。精簡的示例代碼如下,詳細(xì)代碼請見附件中的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實例
- 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的實例依然被自動銷毀了,這說明新的run loop自動創(chuàng)建了一個autorelease pool,這個pool在新的run loop結(jié)束的時候會銷毀自己(并自動release所包含的對象)。
補(bǔ)充說明
在研究retain count的時候,我不建議用NSString。因為在下面的語句中,
- NSString *str1 = @”constant string”;
str1的retain count是個很大的數(shù)字。Objective-C對常量字符串做了特殊處理。
當(dāng)然,如果你這樣創(chuàng)建NSString,得到的retain count依然為1
- NSString *str2 = [NSString stringWithFormat:@”123”];
示例代碼文件鏈接:http://files.cnblogs.com/VinceYuan/objective-c-memman.zip