2011-09-22 15 views
0

的參數的自動釋放對象可能會導致以下代碼出現問題嗎?Objective-C:作爲方法

- (void) method1 { 
     NSMutableArray *myArray = [[[NSMutableArray alloc] init] autorelease]; 

     ... fill the array 

     [someObject someMethod:myArray]; // someObject does work on that array (without retain!) 
} 

一個在我的應用程序有時是出現暴跌看起來這是一個問題;但我不明白......不應該讓myArray至少在method1結束之前保持活躍狀態​​?

非常感謝您的幫助!

所以我的問題除了「這可能是一個問題」,是: - 是否足以移除autorelease,並在方法結束時發佈? - 如果不是:我必須在「someMethod」中保留/釋放嗎?

編輯:但這可能是一個問題,我對嗎?

- (void) method1 { 
     NSMutableArray *myArray = [self getArray]; 

     ... fill the array 

     [someObject someMethod:myArray]; // someObject does work on that array (without retain!) 
} 

- (NSMutableArray) method2 { 
     return [[[NSMutableArray alloc] init] autorelease]; 
} 
+1

Cocoa的所有權規則指定接收的對象應該在調用方法的整個範圍內保持有效,除非您執行以下兩項操作之一:(1)從集合中刪除對象或(2)釋放「父對象」。請參閱[避免導致您正在使用的對象的釋放](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.html#//apple_ref/doc/uid/ 20000043-1000922) – albertamg

回答

0

我要去承擔你的意思這是NSMutableArray而非NSArray片刻。如果你真的在這裏指NSArray,那麼這是完全不可能的。你不能在一個不可變數組上「填充數組」。

是的,這應該工作。你的問題可能在其他地方。這裏常見的錯誤是過度釋放你放入myArray的東西。

+0

抱歉;當然這是NSMutableArray - 我編輯我的問題... – swalkner

0

看起來你缺少分配陣列的行上的幾個開放括號。應該做的將是類似的東西[[[NSMutableArray alloc] init] autorelease];

+0

謝謝;問題編輯:) – swalkner

+0

我通常喜歡使用更簡單(和更短)的'[NSMutableArray數組];'而不是包裝3個調用。 FWIW ... – NSGod

-2

最棒的地方:

- (void) method1 { 
     NSMutableArray *myArray = [[NSMutableArray alloc] init]; 

     ... fill the array 

     [someObject someMethod:myArray]; // someObject does work on that array (without retain!) 
     [myArray release]; 
} 

,它是最好的,從兩個不同的角度。有一種方法是直到你不需要它爲止,所以它不會從內存中擦除,直到你這樣說。其次是同一個句子,只是原因是,只要能夠完成,你將從沒有更多需要的對象中清理內存。
最後可能需要一些更多的解釋...一旦你不需要它,自動釋放對象應該被自動釋放,但是它們被釋放在兩個基本規則上:在塊的末尾(不是總是)或者在內存壓力之後塊的結尾(是的,總是)。換句話說,NSAutoreleasePool並不總是在某些代碼塊的末尾釋放東西,而且它甚至不太可能將這些版本延遲到稍後的時間點。
無論如何,你應該總是檢查過度釋放你的對象,因爲當你試圖在你的代碼中達到這樣的對象時,它會導致崩潰。

+0

主要的自動釋放池事實上在每個運行循環的末尾都耗盡:http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html#//apple_ref/doc/uid/20000047-SW5 –

+0

確實如此,然而不是每一個方法都是一個運行循環,所以你可以發現自己有很多內存用於你不需要很長時間的東西(在編程時間方面秒左右),當你需要它的一些其他的東西,直到它將被釋放在當前運行循環的末尾 – Ariel

0

您的代碼完全是正確。不要聽別人告訴你刪除autorelease,並在撥打someMethod:後手動釋放陣列。

使用autorelease'd對象的案例有99%絕對是對您的應用程序沒有負面的性能影響。你唯一需要擔心的是循環。

[[[Foo alloc] init] autorelease]模式與使用內置輔助方法(如[NSString stringWithFormat:...])相同。他們都返回一個自動釋放的對象,但你可能不擔心後者的性能。再一次,只擔心大循環中的autorelease,或者當Instruments告訴你你有問題時。

使用[[[Foo alloc] init] autorelease]樣式還將所有內存管理保留在一行上。如果你習慣於打字[[[你不會忘記發佈。如果您正在複製粘貼代碼或移動代碼,則不會意外丟失相應的release,因爲它們全部位於同一行。

查看使用[[[Foo alloc] init] autorelease]樣式的代碼也更容易,因爲您不必四處搜索release以確保內存管理是正確的。

因此,在可讀性,安全性和正確性方面,您的代碼絕對是好的。這適用於您的原始代碼段和您在下面添加的後續內容。當你有大循環時,autorelease的性能只會成爲一個問題。

您的崩潰問題必須由您發佈的代碼中不明顯的其他因素引起。

我還建議你閱讀Memory Management Programming Guideline如果你還沒有。基本上,autorelease'd對象保證有效直到封閉池被釋放。在你的情況下,autorelease池在調用堆棧中存在較高的位置(可能是主要的runloop),所以你可以安全地知道你的autorelease'd數組將在你所做的任何調用期間保持有效。

最後一點。你的陣列分配的代碼也可以利用array幫手構造:

NSMutableArray *myArray = [NSMutableArray array]; 

這比原來的更簡單,更清潔和更短。

+0

感謝您的答案,邁克。但是你確定第二個代碼是100%強健的嗎?難道我從method2中獲得的數組在「填充數組」部分中的某處發佈?不太可能,但仍然可能 - 不是嗎? – swalkner

+0

只要你的代碼遵循所有權規則,就沒有什麼可能出錯的。從method2/getArray返回的數組不會被自動釋放,直到代碼返回堆棧。如果'填充數組'的代碼沒有執行保留/複製/等操作就對數組執行釋放,那麼這只是代碼中的錯誤,是的,可能會出錯。但是,如果你所有的代碼都是正確的,並且你只釋放你擁有的對象(即你有alloc/retain/copy'd的對象),那麼一切都很好。 –