2012-08-16 66 views
0

我有兩個問題,但讓我們先從更簡單的問題開始,更加清楚地解釋。爲什麼沒有保留指針需要使用release?

-(void)OnNewFrameData:(NSData *)FrameData 
{ 
    UIImage * I = [UIImage imageWithData:FrameData]; 
    [I release]; 
} 

如果我沒有發佈I,我遇到了內存泄漏。然而,我從來沒有保留I。可以解釋這個嗎? (FrameData完全由來電者管理。)

然後我有關於保留屬性的另一個問題。採取上述相同的代碼,將I分配給保留屬性J,然後將nil分配給相同的保留屬性,不應該有任何泄漏,但是我再次泄漏內存。我也可以發佈保留的財產,但我仍然有泄漏。

@property (retain) UIImage * J; 

... 

-(void)OnNewFrameData:(NSData *)FrameData 
{ 
    UIImage * I = [UIImage imageWithData:FrameData]; 
    self.J = I; 
    // I can also add here [self.J release]; and it still leaks... 
    self.J = nil; 
    [I release]; 
} 

洞察從我所來自的文件,在這裏從線程在計算器得知這兩個混亂的明顯的矛盾將非常感激。

+0

你如何確定你的記憶是否泄漏? – borrrden 2012-08-16 02:18:19

+0

兩三分鐘後(不超過),我得到兩個內存警告,1和2,然後程序退出iOS。視頻幀的尺寸很大,所以我認爲他們正在消耗內存並且沒有獲得釋放。我可以運行相同的代碼大約半小時,並且不會收到任何警告,表明我沒有泄漏內存。有更好的方法嗎? – user574771 2012-08-16 02:24:59

+0

使用隨Xcode提供的儀器工具:http://www.raywenderlich.com/2696/how-to-debug-memory-leaks-with-xcode-and-instruments-tutorial – borrrden 2012-08-16 02:27:26

回答

-1

所以我試着用下面的代碼實驗...

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    UIImage * Img = [[UIImage imageWithData:FrameData] retain]; 
    [pool drain]; 

    int n = [Img retainCount]; 

在上面的代碼中,IMG的保留Count返回1,如果刪除了自動釋放池,它是2。這是絕對明確的證據imageWithData:返回一個自動釋放的對象,這正是我們所期望的。

所以我唯一的結論是游泳池並沒有很快釋放Img,他們正在彙集每一個連續的圖像通過電線。最終我耗盡了內存。

如果沒有人對原始問題的第一部分有任何其他想法,我將不得不以此作爲答案。

我對第二個問題仍然沒有任何線索。

UPDATE:

什麼混淆了我這一切的時候是怎麼做的標記爲自動釋放在主線程對象得到及時釋放?我一直認爲自動發佈就像一個垃圾收集器,只要內存池內存不足就會運行。但回過頭來看,很明顯GB不是自動發佈版本的內容,因爲它可以在非GB的環境中使用。自動釋放池不會釋放任何對象,直到池被消除消息破壞。

那麼主線程對象呢?爲什麼在程序結束之前不能積累?因爲(我在這裏推測,但它是最合理的解釋)每次框架調用我們的類對象之一時(更新:我正在討論調用我們的代碼時調度一個事件的框架),它首先設置一個新的自動釋放池。因此,任何方法中的所有對象都會調用我們的框架所創建的類對象之一,並被新池所包圍,並且在框架從我們的代碼接收控制時釋放所有標記爲自動釋放的對象。

如果有人有任何信息可以更多地瞭解這一點,我非常希望聽到您的消息。

+1

否否否否否否請勿觸摸'-retainCount'。假裝該方法不存在。我不在乎你在做什麼,只是不要。 – 2012-08-17 00:28:29

+0

我非常瞭解訪問retainCount時遇到的問題。我在這裏訪問的目的只是爲了測試[pool drain]的行爲,我們都假設它是來自imageWithData的autorelease對象引用。 – user574771 2012-08-17 04:48:06

+0

有趣的是,有人投票拒絕了我的答案,但無法解釋我所看到的更好的解釋... – user574771 2012-08-20 18:46:48

-1

​​是一種方便的方法,它可以執行下面的操作。

-(UIImage*)imageWithData:(NSData*)data{ 
    UIImage *img = [[UIImage alloc] initWithData:data]; 
    [img autorelease]; 

    return img; 
} 

因此,您可以看到有一個alloc將保留計數設置爲1。希望澄清。如果我可以進一步澄清,請發表評論。我剛剛被提示圖像將被放置在一個autorelease池中,如果你想在游泳池耗盡之後堅持它,應該在創建時保留該圖像。

那麼正確的方法就是使用。

[[UIImage imageWithdata:data]retain]; 

在這樣做時,它將有一個保留計數2,在游泳池流失時會減少一個。因此,你應該只需要一個版本。

p.s您可能還想運行分析儀。它會指出任何內存問題。 (CMD + shift + b)

另一個想法。你可以檢查我不是零。該文檔說,如果它在創建UIImage中失敗,它將返回零,這可能是一個問題。

+1

我不認爲這是正確的,因爲'imageWithData:'不是'alloc','new',或'copy'等命名方法返回一個自動釋放對象 – wattson12 2012-08-16 07:30:30

+0

好了,我看過了。 – geminiCoder 2012-08-16 07:47:57

相關問題