2012-08-16 69 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

相关问题