0

我有两个问题,但让我们先从更容易混淆的问题开始。

-(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 的线程中了解到的这两个令人困惑的明显矛盾。

4

2 回答 2

-1

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

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

   return img;
}

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

正确的方法是使用。

 [[UIImage imageWithdata:data]retain];

在这样做时,它的保留计数为 2,在池耗尽时将减少 1。因此,您仍然应该只需要一个版本。

ps 你可能还想运行分析器。它将指出任何内存问题。(CMD + shift + b)

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

于 2012-08-16T07:24:11.093 回答
-1

所以我尝试了以下代码的实验......

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

    int n = [Img retainCount];

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

所以我唯一的结论是,池没有足够快地释放 Img,他们正在池中通过网络传输的每个连续图像。最终我的记忆力耗尽了。

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

关于第二个问题,我仍然没有任何线索。

更新:

一直让我感到困惑的是,主线程上标记为自动释放的对象如何及时释放?我一直认为自动释放就像一个垃圾收集器,只要内存池内存不足,它就会运行。但回顾文献,很明显 GB 不是自动释放池的意义所在,因为它在非 GB 环境中可用。自动释放池不会释放任何对象,直到池被耗尽消息销毁。

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

如果有人有任何信息可以更清楚地说明这一点,我非常希望收到您的来信。

于 2012-08-16T22:24:00.517 回答