开发者

Why does instruments not find this leak?

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...

Why does instruments not find this leak?


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.


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.


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.


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.


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜