为什么仪器没有发现这种泄漏?

时间:2011-04-17 19:42:00

标签: objective-c xcode memory-management static-analysis instruments

快一个人。快速浏览下面的代码片段。我分配 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;
}

编辑:静态分析器的输出...

enter image description here

5 个答案:

答案 0 :(得分:4)

仪器的泄漏检测通过保守扫描内存,寻找指针和构建分配之间的连接图来实现。如果它找到了可以从全局变量或堆栈变量到达的内存中对象的任何指针,则该对象不能被视为泄露。

乐器不知道指针的布局或上下文。如果你是malloc(1024)并且在那个[再循环]的内存块中碰巧有一堆指针,那么即使你再也不会将这些指针视为真正的引用,这些指针也会计算在内。

所以,不,泄漏永远不会100%准确。同样,泄漏内存的方法远远多于实际泄漏。如果您有全局缓存,请执行以下操作:

 NSMutableDictionary *myGlobalCache;

你要填充那个缓存,但从不修剪它,这将是一个有效的内存泄漏,并且没有任何方式它会出现在仪器中。

我写了一篇关于Heapshot analysis的深入讨论,这篇讨论是相关的,也可能是有意义的。

答案 1 :(得分:2)

让我猜一下,newReadOnlyCellWithTitle:andText:时,您-tableView:cellForRowAtIndexPath:方法会调用cell == nil

问题是,这些单元格不会被释放,它们会被-dequeueReusableCellWithIdentifier:缓存并撤回。表视图反复使用相同的单元格,因此减少了不断分配和释放内存的需要。

为了确保这种情况,您可以尝试切换到不同的视图控制器,然后在模拟器中模拟内存警告。这将强制释放先前控制器的视图,并因此在讨论中的单元格上释放。您应该注意到仪器泄漏。

答案 2 :(得分:1)

我想你只有在没有有效参考时才会看到它。

所以,在你的情况下,仍然有一个有效的参考,例如,(可能)屏幕 - &gt;表 - &gt;细胞 - &gt;标签。看起来您的屏幕(主视图)仍有可能仍在内存中,因此仍然是有效的参考。

您可能希望检查已分配但未释放的对象,并仍将其作为有效对象保留在内存中。检查泄漏并不总是足够的。

答案 3 :(得分:1)

泄漏只会找到任何其他对象未引用的对象。例如,如果在一个方法中创建两个对象,这些对象彼此引用但没有其他人引用其中任何一个,则它们都是技术上泄露的对象,但是泄漏可以看到它们,因为它们每个都有一个引用它们的对象。静态分析仪非常擅长发现这些类型的东西,所以两个在演唱会中几乎可以杀死任何泄漏。

答案 4 :(得分:-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?