4

快速的一個人。快速瀏覽下面的代碼片段。我分配UILabel * textLabel但我不釋放它(註釋掉)。當方法結束時,我失去了指針的引用,所以它會泄漏。爲什麼儀器不能找到這個泄漏?

問題是XCode Instruments沒有發現這個泄漏,我會認爲它是一個非常簡單的情況下找到它。它沒有在我的應用程序中報告任何泄漏,但我自己發現了這一個,這讓我有點懷疑。

我是在看東西還是在檢測泄漏的儀器方面很差?

-(UITableViewCell*)newReadOnlyCellWithTitle:(NSString*)title andText:(NSString*)text { 
    UITableViewCell *cell=[[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease]; 
    cell.textLabel.text=title; 
    cell.selectionStyle=UITableViewCellSelectionStyleNone; 
    cell.backgroundColor=[UIColor whiteColor]; 
    cell.opaque=YES; 

    UILabel *textLabel=[[UILabel alloc] initWithFrame:CGRectMake(80, 11, 350, 24)]; 
    textLabel.text=text; 
    textLabel.textColor=[UIColor lightTextColor]; 
    textLabel.font=[UIFont fontWithName:STANDARD_FONT size:16.0]; 
    textLabel.opaque=YES; 
    textLabel.backgroundColor=[UIColor clearColor]; 
    [cell.contentView addSubview:textLabel]; 
    //[textLabel release]; //<== without the release this should leak, yep? 
    return cell; 
} 

編輯:從靜態analyizer輸出...

enter image description here

+1

構建和分析(CMD + SHIFT + B)應該找到它:) – cweinberger 2011-04-17 20:11:28

+0

優秀的一點。靜態分析儀確實找到它! – Damien 2011-04-17 20:14:05

+0

@theMikeSwan嗨,我想如果你把你的評論作爲答案,我會把它標記爲正確的。 – Damien 2011-04-17 22:08:18

回答

4

儀器的泄漏檢測通過保守地掃描內存,尋找指針並建立分配之間的連接圖。如果它找到可以從全局變量或堆棧變量到達的內存中的對象的指針,那麼該對象不能被認爲是泄漏的。

儀器不知道指針的佈局或上下文。如果你使用了malloc(1024),並且在[回收]內存塊中碰巧有一堆指針,那麼即使你再也不會將這些指針作爲真正的引用來處理,那麼這些指針將會被計數。

因此,不,泄漏永遠不可能100%準確。同樣,泄漏內存的方式比實際泄漏要多得多。如果你有一個全局緩存,就像這樣:

NSMutableDictionary *myGlobalCache; 

而且你要填補緩存,但從來沒有修剪它,那將是一個有效的內存泄漏,也沒有辦法,它會在每一個儀表顯示。

我寫了一篇關於Heapshot analysis的深入討論,這是相關的,可能是有趣的。

-2

你缺少有2個指針

本地你有對象

UILabel *textLabel=[[UILabel alloc] initWithFrame:CGRectMake(80, 11, 350, 24)]; 

而且在窗口系統將管理它,你(這是我的理解它是不是製作副本,但取得所有權)

[cell.contentView addSubview:textLabel]; 

所以釋放是不必要的,並與我有限的知識即使是不好的。

//[textLabel release]; //<== without the release this should leak, yep? 
+0

我不是內存管理方面的專家,但我認爲這個版本是必需的。它可能是一個[.. autorelease],但它仍然需要維護正確的retainCount。 – govi 2011-04-17 19:58:43

+0

嗨格雷格。感謝您的回答。首先,我同意我的本地名稱很糟糕(這是一個深夜!),所以我已經改名了,但我仍然有這個問題。我的理解是,添加子視圖將保留標籤,但由於我沒有自己釋放所有權,它永遠不會釋放(保留數量將太高),但我沒有對該對象的引用。所以在我的書中,仍然是一個泄漏......我認爲:-) – Damien 2011-04-17 20:00:06

+0

我在我的代碼中添加了發行版。但是,雖然不是「依賴」樂器成爲我的泥衛隊,但我會認爲它可以找到像這樣直截了當的泄漏。除非它不是泄漏,我完全誤解了一些東西。 – Damien 2011-04-17 20:01:32

1

我想你會看到它只有當沒有有效的引用。

因此,在你的情況下,仍然有一個有效的引用,類似於(可能)類似於Screen - > table - > cell - > label。看起來您的屏幕(主視圖)仍然存在於內存中,因此仍然是有效的參考。

您可能希望檢查已分配但未釋放的對象,並將其保留在內存中作爲有效對象。檢查泄漏並不總是足夠的。

+0

有趣的govi。我會在你的想法中做一些調查......肯定是值得思考的。 – Damien 2011-04-17 20:05:48

+0

即時消息有興趣知道結果以及:) – govi 2011-04-17 20:18:47

+0

我會回來的! (俗話說!) – Damien 2011-04-17 20:23:33

2

讓我猜, - newReadOnlyCellWithTitle:andText:-tableView:cellForRowAtIndexPath:方法調用的時候cell == nil

問題是,這些單元格沒有被釋放,它們被緩存並被-dequeueReusableCellWithIdentifier:拉回。表視圖一次又一次地使用相同的單元格,從而減少了不斷分配和釋放內存的需要。

要確保是這種情況,您可以嘗試切換到不同的視圖控制器,然後在模擬器中模擬內存警告。這將強制釋放前一個控制器的視圖,並因此討論單元格。您應該注意到樂器中存在泄漏。

+0

嗨巴託什。感謝您的詳細解答。對govi也有類似的想法,我也開始這麼想。我懷疑我的看法中的某些東西並不像它應該那樣運作良好。這是在我的應用程序的一個晦澀的地方。在我的代碼片段中,我將__reuseIdentifier__設置爲零。所以我不會期望它被重用。沒有特別的原因,我沒有使用reuseIdentifier,但我想這是我的應用程序的一部分,代碼並不是很棒 - 因此我今天晚上對它進行了審查! – Damien 2011-04-17 20:12:37

1

泄漏只會找到沒有被任何其他對象引用的對象。例如,如果您在引用對方的方法中創建了兩個對象,但沒有其他人引用它們中的任何一個,則它們在技術上都是泄漏對象,但泄漏可以看到它們,因爲它們每個都有引用它們的對象。靜態分析儀在找到這些東西的時候非常好,所以這兩個音樂會幾乎可以消除任何泄漏。