为什么仪器检测不到这种泄漏?

发布于 2024-11-01 14:51:19 字数 1199 浏览 1 评论 0原文

快点吧伙计们。快速浏览一下下面的代码片段。我分配了 UILabel *textLabel 但我没有释放它(已注释掉)。当方法结束时,我失去了对指针的引用,因此它泄漏了。

问题是 XCode Instruments 没有发现这个泄漏,我认为它找到它是一个非常简单的情况。它没有报告我的应用程序中的任何泄漏,但我自己发现了这个,这让我有点怀疑。

是我疏忽了,还是 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;
}

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

在此处输入图像描述

Quick one folks. Have a quick look at the code snippet below. I alloc the UILabel *textLabel but I don't release it (commented out). When the method ends, I lose reference to the pointer so it leaks.

Thing is that XCode Instruments doesn't find this leak and I would have thought that it is quite a straightforward case for it to find it. Its not reporting any leaks in my application and yet I found this one myself and its made me a little suspicious.

Am I over looking something or is Instruments rather poor at detecting leaks?

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

Edit: output from static analyizer...

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

甜味超标? 2024-11-08 14:51:20

你错过了有两个指向该对象的指针

本地你有

UILabel *textLabel=[[UILabel alloc] initWithFrame:CGRectMake(80, 11, 350, 24)];

并且在窗口系统中将为你管理它(据我所知,它不是制作副本,而是取得所有权)

[cell.contentView addSubview:textLabel];

所以释放是不必要的,并且以我有限的知识甚至很糟糕。

//[textLabel release]; //<== without the release this should leak, yep?

Your missing that there are 2 pointers to the object

Locally you have

UILabel *textLabel=[[UILabel alloc] initWithFrame:CGRectMake(80, 11, 350, 24)];

And within the windowing system which will manage it for you (it is my understanding it is not making a copy, but taking ownership)

[cell.contentView addSubview:textLabel];

So release is unnecessary, and with my limited knowledge even bad.

//[textLabel release]; //<== without the release this should leak, yep?
纸伞微斜 2024-11-08 14:51:19

Instrument 的泄漏检测通过保守地扫描内存、查找指针并构建分配之间的连接图来工作。如果它发现任何指向内存中可以从全局变量或堆栈变量访问的对象的指针,则该对象不能被视为泄漏。

Instruments 不知道指针的布局或上下文。如果您要使用 malloc(1024) 并且该[回收的]内存块中碰巧有一堆指针,那么即使您再也不会将这些指针视为真正的引用,这些指针也会被计数。

所以,不,Leaks 永远不可能 100% 准确。同样,内存泄漏的方式比实际泄漏的方式要多得多。如果您有一个全局缓存,如下所示:

 NSMutableDictionary *myGlobalCache;

并且您要填充该缓存但从不修剪它,这将是一个有效的内存泄漏,并且它不可能每次都出现在 Instruments 中。

我写了一篇深入讨论 Heapshot 分析,这是相关的并且可能令人感兴趣。

Instrument's leak detection works by conservatively scanning memory, looking for pointers and building a graph of connections between allocations. If it finds any pointer(s) to an object in memory that can be reached from a global variable or stack variable, then that object cannot be considered leaked.

Instruments does not know the layout or context of a pointer. If you were to malloc(1024) and there happened to be a bunch of pointers in that [recycled] chunk of memory, those would count even though you will never treat those pointers as real references again.

So, no, Leaks can never be 100% accurate. As well, there are far more many ways to leak memory than an actual leak. If you had a global cache, like this:

 NSMutableDictionary *myGlobalCache;

And you were to fill that cache but never prune it, that would be an effective memory leak and there is no way that it'll every show up in Instruments.

I wrote up an in depth discussion of Heapshot analysis, which is related and may be of interest.

如此安好 2024-11-08 14:51:19

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

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

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

Let me guess, -newReadOnlyCellWithTitle:andText: gets called by your -tableView:cellForRowAtIndexPath: method when cell == nil?

The thing is, those cells don't get released, they are cached and pulled back by -dequeueReusableCellWithIdentifier:. Table view uses same cells over and over again thus reducing the need to constantly allocate and release memory.

To make sure this is the case, you can try switching to different view controller, then simulating memory warning in simulator. This will force release on previous controller's view and as a result on cells in discussion. You should notice a leak in Instruments.

月竹挽风 2024-11-08 14:51:19

我认为只有在没有有效参考资料的情况下你才会看到它。

因此,就您而言,仍然有一个有效的参考,类似于(可能)屏幕 ->表->细胞->标签。看起来您的屏幕(主视图)可能仍在内存中,因此仍然是有效的参考。

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

I think u will see it only when there are no valid references.

So, in your case, there is still a valid reference that goes something like, (probably) Screen -> table -> cell -> label. Looks like there is a possibility that your screen, the primary view, is still in memory, and hence still a valid reference.

You might want to check the objects that are allocated and then not released and still stay in the memory as valid objects. Checking for leaks isn't always enough.

熟人话多 2024-11-08 14:51:19

泄漏只会找到未被任何其他对象引用的对象。例如,如果您在一个方法中创建两个相互引用的对象,但没有其他人引用它们中的任何一个,那么它们在技术上都是泄漏对象,但泄漏可以看到它们,因为它们每个都有一个引用它们的对象。静态分析器非常擅长发现这类事情,因此两者结合起来应该可以消除几乎所有泄漏。

Leaks will only find objects that are not referred to by any other object. For example if you create two objects in a method that refer to each other but no one else refers to either of them they are both technically leaked objects but leaks can see them since they each have an object that refers to them. Static analyzer is pretty good at finding these kinds of things though so the two in concert should kill almost any leak.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文