2014-04-30 58 views
5

創建一個ARC新項目並在didFinishLaunchingWithOptions中注入此代碼。NSNumber可能的內存泄漏

for (int i=0; i < 1000000; i++) { 
    NSNumber* num = [NSNumber numberWithInt:i]; 
    NSLog(@"%@", num); 
} 

NSLog(@"over"); 

應用程序的內存將增加。 另外,在for循環結束時,內存不會減少。

但是,如果在同一for循環替換:

NSNumber* num = [NSNumber numberWithInt:i]; 

通過

NSNumber* num = [[NSNumber alloc] initWithInt:i]; 

那麼內存將保持穩定。

這是預期的行爲?

編輯:

好了,讓我們把didFinishLaunchingWithOptions上側的時刻。 您仍然可以放入viewDidLoad並刪除零以便更快地達到for循環的末尾 應用程序的內存將增長至〜11 MB。當for循環結束時,內存不會減少。它仍然在〜11 MB。

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    for (int i=0; i < 100000; i++) { 
     NSNumber* num = [NSNumber numberWithInt:i]; 
     NSLog(@"%@", num); 
    } 

    NSLog(@"over"); 
} 

如果你去:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    @autoreleasepool { 
     for (int i=0; i < 100000; i++) { 
      NSNumber* num = [NSNumber numberWithInt:i]; 
      NSLog(@"%@", num); 
     } 
    } 

    NSLog(@"over"); 
} 

驚喜!驚喜! 你會有完全相同的行爲。你會達到〜11 MB,內存不會減少。然而,將@autorelease放在循環內部也是可行的......但在這裏,我並沒有試圖讓事情順利運行,而是理解爲什麼在for循環結束時內存不會流失。

所以,問題仍然存在。

+0

有趣..等待專家的意見就這一個.. – rdurand

+0

如果你把'@autoreleasepool {...}'周圍的'for'聲明? – trojanfoe

+0

您是否嘗試過其他基礎課程?另一種類型的init(例如initWithBool)呢? – rdurand

回答

3

這是預期的。當您使用alloc/init分配NSNumber時,ARC將在不再需要時立即釋放它。

當您使用便捷方法(如numberWithInt:)分配它時,您將獲得的是在autorelease池中分配的對象。在autorelease池耗盡之前,你的內存不會被釋放。但是,你可以爲你的循環像這樣創建一個自動釋放池:

for (int i=0; i < 1000000; i++) @autoreleasepool { 
    NSNumber* num = [NSNumber numberWithInt:i]; 
    NSLog(@"%@", num); 
} 

NSLog(@"over"); 

這應該釋放號碼後每看一次迭代。

您可以在這裏進一步的細節: Memory Management Policy

+1

這不可能是原因。主線程已經有了一個autorelease池,它在每個runloop跳躍中都被耗盡。這些數字將在'application:didFinishLaunchingWithOptions:'退出後一段時間釋放。 – hamstergene

+0

@trojanfoe是的,它會。 – Jorge

+0

確實。不尋常的語法,但。 – trojanfoe