为什么没有保留指针需要使用释放?

时间:2012-08-16 01:55:14

标签: objective-c ios

我有两个问题,但是首先要考虑简单性问题,让问题更加清晰。

-(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];
}

从我从文档和stackoverflow中的线程中学到的这两个令人困惑的明显矛盾的洞察将非常感激。

2 个答案:

答案 0 :(得分:-1)

[UIImage imageWithData]是一种方便的方法,可以执行以下操作。

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

   return img;
}

因此您可以看到有一个alloc将retain count设置为1。希望这澄清一下。如果我能进一步澄清,请发表评论。我刚刚被提示将图像放置在自动释放池中,如果您想在池耗尽后保留它,则应该在创建时保留该图像。

然后使用正确的方法。

 [[UIImage imageWithdata:data]retain];

在执行此操作时,它将具有2的保留计数,在池消耗时将减少1。因此,您仍然只需要一个版本。

p.s您可能还想运行分析仪。它会指出任何内存问题。 (CMD + shift + b)

另一种想法。你能检查我不是零。文档说如果它在创建UIImage时不成功,它将返回nil,这可能是一个问题。

答案 1 :(得分:-1)

所以我尝试使用以下代码进行实验......

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

    int n = [Img retainCount];

在上面的代码中,Img的保留计数返回1.如果我删除了自动释放池,则为2.这绝对清楚地表明imageWithData:返回一个自动释放的对象,这正是我们所期望的。 / p>

所以我唯一的结论是,游泳池不会很快释放出来,并且他们正在汇集每一个连续的图像来自电线。最终我的内存不足了。

如果没有人对原始问题的第一部分有任何其他想法,我将不得不将其作为答案。

我对第二个问题仍然没有任何线索。

更新:

一直困扰我的是主要线程上标记为自动释放的对象如何及时释放?我一直认为自动释放就像一个垃圾收集器,只要内存池内存不足就会运行。但回顾文献,很明显GB不是自动发布池的内容,因为它可以在非GB环境中使用。在使用排除消息销毁池之前,自动释放池不会释放任何对象。

那么主线程对象呢?为什么在程序结束之前它们不会累积?因为(我在这里猜测,但这是最合乎逻辑的解释)每次框架调用我们的一个类对象时(UPDATE:我说的是每当调度一个事件时调用我们的代码的框架),它首先建立一个新的自动释放池。因此,当框架从我们的代码接收控制权时,任何方法中的所有对象都会调用由框架生成的我们的类对象之一被新鲜池包围,并且标记为自动释放的所有对象都会被释放。

如果有人有任何信息可以提供更多信息,我非常希望收到你的来信。