4

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

编辑:从静态analyizer输出...

enter image description here

+1

构建和分析(CMD + SHIFT + B)应该找到它:) – cweinberger 2011-04-17 20:11:28

+0

优秀的一点。静态分析仪确实找到它! – Damien 2011-04-17 20:14:05

+0

@theMikeSwan嗨,我想如果你把你的评论作为答案,我会把它标记为正确的。 – Damien 2011-04-17 22:08:18

回答

4

仪器的泄漏检测通过保守地扫描内存,寻找指针并建立分配之间的连接图。如果它找到可以从全局变量或堆栈变量到达的内存中的对象的指针,那么该对象不能被认为是泄漏的。

仪器不知道指针的布局或上下文。如果你使用了malloc(1024),并且在[回收]内存块中碰巧有一堆指针,那么即使你再也不会将这些指针作为真正的引用来处理,那么这些指针将会被计数。

因此,不,泄漏永远不可能100%准确。同样,泄漏内存的方式比实际泄漏要多得多。如果你有一个全局缓存,就像这样:

NSMutableDictionary *myGlobalCache; 

而且你要填补缓存,但从来没有修剪它,那将是一个有效的内存泄漏,也没有办法,它会在每一个仪表显示。

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

-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? 
+0

我不是内存管理方面的专家,但我认为这个版本是必需的。它可能是一个[.. autorelease],但它仍然需要维护正确的retainCount。 – govi 2011-04-17 19:58:43

+0

嗨格雷格。感谢您的回答。首先,我同意我的本地名称很糟糕(这是一个深夜!),所以我已经改名了,但我仍然有这个问题。我的理解是,添加子视图将保留标签,但由于我没有自己释放所有权,它永远不会释放(保留数量将太高),但我没有对该对象的引用。所以在我的书中,仍然是一个泄漏......我认为:-) – Damien 2011-04-17 20:00:06

+0

我在我的代码中添加了发行版。但是,虽然不是“依赖”乐器成为我的泥卫队,但我会认为它可以找到像这样直截了当的泄漏。除非它不是泄漏,我完全误解了一些东西。 – Damien 2011-04-17 20:01:32

1

我想你会看到它只有当没有有效的引用。

因此,在你的情况下,仍然有一个有效的引用,类似于(可能)类似于Screen - > table - > cell - > label。看起来您的屏幕(主视图)仍然存在于内存中,因此仍然是有效的参考。

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

+0

有趣的govi。我会在你的想法中做一些调查......肯定是值得思考的。 – Damien 2011-04-17 20:05:48

+0

即时消息有兴趣知道结果以及:) – govi 2011-04-17 20:18:47

+0

我会回来的! (俗话说!) – Damien 2011-04-17 20:23:33

2

让我猜, - newReadOnlyCellWithTitle:andText:-tableView:cellForRowAtIndexPath:方法调用的时候cell == nil

问题是,这些单元格没有被释放,它们被缓存并被-dequeueReusableCellWithIdentifier:拉回。表视图一次又一次地使用相同的单元格,从而减少了不断分配和释放内存的需要。

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

+0

嗨巴托什。感谢您的详细解答。对govi也有类似的想法,我也开始这么想。我怀疑我的看法中的某些东西并不像它应该那样运作良好。这是在我的应用程序的一个晦涩的地方。在我的代码片段中,我将__reuseIdentifier__设置为零。所以我不会期望它被重用。没有特别的原因,我没有使用reuseIdentifier,但我想这是我的应用程序的一部分,代码并不是很棒 - 因此我今天晚上对它进行了审查! – Damien 2011-04-17 20:12:37

1

泄漏只会找到没有被任何其他对象引用的对象。例如,如果您在引用对方的方法中创建了两个对象,但没有其他人引用它们中的任何一个,则它们在技术上都是泄漏对象,但泄漏可以看到它们,因为它们每个都有引用它们的对象。静态分析仪在找到这些东西的时候非常好,所以这两个音乐会几乎可以消除任何泄漏。