2010-04-20 49 views
1

iPhone NSCFString泄漏在下面的代碼:在fetchRequest

- (NSMutableArray *) fetchNotesForGroup: (NSString *)groupName { 

// Variables declaration 
NSMutableArray *result; 
NSFetchRequest *fetchRequest; 
NSEntityDescription *entity; 
NSSortDescriptor *sortDescriptor; 
NSPredicate *searchPredicate; 
NSError *error = nil; 

// Creates the fetchRequest and executes it 
fetchRequest = [[[NSFetchRequest alloc] init] autorelease]; 
entity = [NSEntityDescription entityForName:@"Note" inManagedObjectContext:managedObjectContext]; 
[fetchRequest setEntity:entity]; 
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"noteName" ascending:YES] autorelease]; 
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]]; 
[fetchRequest setReturnsDistinctResults:YES]; 
searchPredicate = [NSPredicate predicateWithFormat:@"categoryName like %@", groupName]; 
[fetchRequest setPredicate:searchPredicate]; 
[fetchRequest setPropertiesToFetch:[NSArray arrayWithObject:@"noteName"]]; 
result = [[managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy]; 

// Variables release 

return result; 
} 

...我取了一個給定的類別名稱註釋。當我運行Instruments時,它說NSCFString正在泄漏。

我知道泄漏對於iPhone開發者來說意味着什麼......但我對如何插入這個漏洞並不知情。

任何線索?歡迎所有幫助。

非常感謝!

回答

1

你的問題是這樣的:

result = [[managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy]; 
// Variables release 
return result; 

mutableCopy返回所屬引用(即用+1的對象保留計數),您有責任(自動)釋放。你沒有,然後你放棄了參考,這意味着你已經泄露了陣列。使用return [result autorelease];代替。

+0

感謝您的答案。我試圖釋放自己的(而不是autorelease),並沒有解決。 我使用它釋放了另一個函數的數組,並且泄漏仍然存在... 猜猜我必須嘗試其他一些...不知道是什麼。 – camilo 2010-04-20 19:11:24

+0

嘿,我什至沒有看到可變的副本。猜猜這會教我滾動一路。無論如何,你不應該在這裏複製,而應該在你發送數組的對象中。 – TechZen 2010-04-20 21:55:16

+1

我不認爲Instruments從絕對意義上追蹤泄漏,而是尋找持續超出其預期範圍的對象。如果您沒有遵循管理保留的標準方法,那麼您可能會發現樂器在被創建它們的範圍消失之後仍然存在的對象混淆。 – TechZen 2010-04-20 21:57:30

0

首先,樂器可能並不總是準確的。
它可以在某些特殊情況下報告泄漏,只是因爲它沒有看到您實際上在其他地方釋放了該對象。

也有可能CF的某些部分有泄漏。

我在代碼中看到的是您正在使用自動釋放的對象。
你是臨時性的對象將有一個很長的生命週期。
如果您在方法返回之前明確地釋放它們,那麼會附加什麼?

您還正在返回一個對象的副本。
您必須確保該對象在某個時刻被釋放。
返回一個自動釋放的對象可能會好得多,並讓調用方法決定是否應該保留該對象。

0

由於您沒有創建任何字符串,因此泄漏的字符串很可能是取得請求內部的最後一個字符串,並且很可能是實際發生泄漏的提取請求。 (在儀表顯示的調用堆棧應確認這一點。)

我不認爲你有一個實際的泄漏,但是通過這樣做:

fetchRequest = [[[NSFetchRequest alloc] init] autorelease]; 

...您允許的fetchRequest住超越它定義的範圍儀器會將其解釋爲泄漏。

自動釋放實際上使對象比直接釋放更長的時間,因爲它會導致對象掛起,直到外部自動釋放池被耗盡。例如,如果在object-A中創建object-B並將其返回給object-C autoreleased,則在object-A被釋放後即使object-C從不保留它,object-B也會長時間保持活動狀態。 (儘管它最終會在不可預知的時刻死亡。)

自動釋放不是一種方便的方法來保留。它具有保留在其他對象之間傳遞的對象的特定目的。如果你不這樣做,不要使用autorelease。

如果你這樣做:

fetchRequest = [[NSFetchRequest alloc] init]; 
// ... 
[fetchRequest release]; 

...您的泄漏會自行消失。

你可能會,但是,要做到這一點:

return [result autorelease]; 

...以確保結果數組的壽命足夠長,以便被另一個對象保留。

+0

首先:autorelease可以絕對用作釋放對象的一種方便方法。這是一個折衷 - 可讀性/便利性與可能的短期RAM膨脹。爲了便於閱讀,我傾向於使用自動釋放對象,除非我處於循環或代碼的其他「熱」部分,或者對象使用大量內存。其次:儀器不能正確顯示自動釋放的物體是否泄漏 - 請親自嘗試。 – 2010-04-21 15:11:46

+0

@尼克福奇 - 這是一個常見的錯誤。蘋果公司的文件非常清楚,它不是一種方便的方法。你似乎錯過的反面是一個自動迴歸的物體可以隨時在任何範圍內死亡。你已經知道了,因爲你一直在寫簡單的代碼。如果你已經嚴格管理內存和自定義發佈池,你會發現這樣的草率練習有多危險。 – TechZen 2010-04-22 14:17:51

+0

這不是「馬虎」,也不是「錯誤」,這是一種折衷,不同的人對此有不同的理念。您更喜歡優先考慮RAM優化而不是可讀性,這很好。你可以自由地做到這一點。但是,導致使用autorelease而不是release的任何錯誤都是由於代碼中存在其他問題(例如,未將代理設置爲nil或類似的東西)。看到這個問題(和許多有見地的答案)對這個主題的廣泛意見:http://stackoverflow.com/questions/193288/what-is-the-cost-of-using-autorelease-in-cocoa – 2010-04-22 15:12:56

相關問題