2015-05-01 31 views
-4

我們假設我們使用Xcode創建了一個新的MacOS應用程序,並在[viewDidLoad]中添加了一些代碼。爲什麼不使用後釋放內存NSMutableArray

運行後內存未完全釋放。爲什麼?如何釋放內存?

示例代碼:

NSMutableArray *a = [NSMutableArray array]; 

for(int i=0;i<8000000;i++){ 
    [a addObject:[NSValue valueWithPoint:NSMakePoint(i, 0)]]; 
} 
a = nil; 

我可以通過一個按鈕,名稱是看到內存imformation通過Xcode的

+0

請描述你如何測量內存消耗。 – user3125367

+0

我已經使用了ARC – LERO

+0

你是如何測量內存消耗的? –

回答

1

「顯示調試導航」如果你正在使用ARC那你就不要關心釋放。如果你在手動內存管理模式下運行這個代碼,那麼在這種情況下你仍然不用擔心內存,因爲它所擁有的數組和對象都是自動釋放的。所以這個代碼是完全確定,不能造成任何內存泄漏

+0

但內存看起來很高,不能下降,爲什麼?你能解決它嗎? – LERO

+2

也許是因爲你正在創建8百萬個對象?如果您爲了您的需要而消耗太多內存,您如何期望將內存保持在較低水平 –

+0

您確實在使用很多對象。如果您的類實例從內存中釋放,則內存會再次下降。你寫過你在viewDidLoad中使用for循環。這意味着代碼在視圖控制器內執行。如果釋放對視圖控制器的所有引用,內存將再次釋放。如果您在主視圖控制器中執行此操作,關閉應用程序後內存將被釋放。 – JackPearse

0

您可以使用@autoreleasepool:

@autoreleasepool { 
    for(int i=0;i<8000000;i++){ 
     [a addObject:[NSValue valueWithPoint:NSMakePoint(i, 0)]]; 
    } 
} 
+1

爲什麼我需要添加@autoreleasepool? 我已經使用ARC了,代碼的用處是什麼? – LERO

+0

你實際上應該在這種情況下使用@autoreleasepool - 如果你想在釋放它們之後(即使使用ARC)。你基本上是在創建8kk的對象,並且在循環之後,他們將被全部清除,當你可以添加該塊來在autoreleasepool之後釋放臨時對象時。看一看:https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html – sunshinejr

+2

即使'@ autoreleasepool'在這種情況下是值得的(不清楚它是什麼) ,它應該放在整個for語句中(假設它的範圍真的有限),而不是每次迭代。 –

2

首先讓我們對你做了什麼樣子:

NSMutableArray *a = [NSMutableArray array]; 
for(int i=0;i<8000000;i++){ 
    [a addObject:[NSValue valueWithPoint:NSMakePoint(i, 0)]]; 
} 
a = nil; 

創建autorelease池中的數組,並在autorelease池中創建一些值對象。自動發佈的數組包含值對象。

答:只要有一個autorelease池,沒有任何對象將被釋放。 autorelease池保留它們。因此設置anil不會真的有幫助。只要自動釋放池保留的對象,放棄私人蔘考不能把引用計數爲0

有兩種技術,以避免:

一個。正如@sunshine所提到的,您可以安裝本地自動釋放池。這將保存對象而不是更全局的自動釋放池,從而更早地釋放對象。 (但正如@HotLicks所說,如果應該放在整個片段之外)。

b。不要在autorelease池中創建對象。

NSMutableArray *a = [NSMutableArray new]; // new is ownership transfer 
for(int i=0;i<8000000;i++) { 
    CGPoint point = NSMakePoint(i, 0); 
    [a addObject:[[NSValue alloc] initWithBytes:&point withObjCType:withObjCType:@encode(CGPoint)]; 
} 
a = nil; 

B.有可能您仍然有「幽靈般的」物體。這可能是因爲某些價值等級(即NSNumber)永遠不會釋放一些在不久的將來被重新使用的對象。當使用valueWithPoint:時,可能NSValue也是如此。沒有相應的-initWithPoint:是一個指針。

如果您告訴我們,您可以期待更好的信息,您如何衡量內存消耗。 「ARC」沒有回答這個問題,因爲它是一個內存管理模型,沒有內存測量工具。

+0

我可以通過一個名爲「show the debug navigator」的按鈕來查看關於內存的信息,你在哪裏?我無法發佈圖片。 – LERO

+1

我知道Xcode的調試導航器中的內存顯示。謝謝。它顯示應用程序的整體內存消耗。它與實例對象無關,也不是內存泄漏的指針。 (即使你有時讀過,它仍然是錯誤的*)。有幾個原因導致應用程序沒有在系統時間釋放系統保留的內存。 –

+0

事實是,即使存在顯式/隱式版本和池,系統級別的內存也可能無法回收。任何隱藏的框架級分配可能會阻止頁面返回到系統,因此內存將被標記爲空閒,但指紋可能無限期地保持高位。這並不意味着進一步的分配會堆積如山,因爲現在有很多框架/克隆級可用空間。 – user3125367

0

使用ARC並不能保證你的對象會被釋放或告訴你它們何時被釋放。一切都在幕後自動完成。

當我說你的對象不能保證被釋放時,考慮即使使用ARC也仍然是現實的保留(強)循環。

因此,你的代碼在這一點上是好的,但是如果你想強制釋放,就像一位同事提到的那樣,將你的本地對象嵌入到一個@autoreleasepool塊中,當它的執行完成時它將被耗盡。