开发者

Leaks (instrument) reports leaks in autoreleased objects

Update: this leak has been solved. If you are getting similar leaks and your application is multi-threading, you are most likely making UIKit calls from a background thread; make use of e.g. [NSThread performSelectorOnMainThread:] to route UIKit calls out to the main thread, which is the only place where they are allowed.

I've been running Leaks on my current project to find leaks lately, and I keep running into these "leaks" which from what I can tell aren't really leaks. The following code, taken directly from the project, has two leaks, according to Leaks:

- (NSArray *)areaForIndex:(int)index 
{
    NSMutableArray *a = [NSMutableArray arrayWithArray:
        [world  retrieveNeighborsForIndex:index]]; // leak 1
    [a insertObject:[references objectAtIndex:index] atIndex:0];
    return [NSArray arrayWithArray:a]; // leak 2
}

Leak 1 goes away if I change the first line to: (see Update 2-3)

Leak 2 goes away if I change the last line to:

    return a;

I can't unfortunately do that with leak 1 because I'm casting an immutable array into a mutable one. Still, arrayWithArray is supposed to autorelease, anyway, so from what I can tell, it shouldn't leak anything. Any ideas why this is happening?

Update: I've tested this on both the device and the Simulator. The leak is there on both. However, on the Simulator I get some additional information about this leak:

The history for the leak goes as follows:

# | Category | Event Type  | Timestamp | RefCt |  Address  | Size | Responsible Library | Responsible Caller
--+----------+-------------+
0 | CFArray  | Malloc      | 00:09.598 |     1 | 0x474f6d0 |   48 | asynchro            | -[muddyGrid areaForIndex:]
1 | CFArray  | Autorelease | 00:09.598 |       | 0x474f6d0 |    0 | Foundation          | NSRecordAllocationEvent
2 | CFArray  | CFRetain    | 00:09.598 |     2 | 0x474f7d0 |    0 | Foundation          | -[NSCFArray retain]
3 | CFArray  | CFRelease   | 00:09.611 |     1 | 0x474f7d0 |    0 | Foundation          | NSPopAutoreleasePool

The things I can discern from the above is that the autoreleased array is somehow retained twice and then autoreleased, leaving retain count at 1. No idea where or why though...

Update 2 & 3: I tried changing the line for Leak 1 to:

    NSMutableArray *a = [[[NSMutableArray alloc] initWithArray:
        [world retrieveNeighborsForIndex:inde开发者_StackOverflow中文版x]] autorelease];

I thought this removed the leak, but it didn't, ultimately. So I'm still at a loss.


Anticlimactically, this one solved itself as I solved a bunch of other issues with my code.

Mainly, the code had a number of places where UI updates were made outside of the main thread, which is a big no-no. One of these other unrelated issues must have triggered the memory leak in the above code, since it doesn't report any leaks anymore (I have 0 leaks as it stands), although I haven't modified the code any.


What retrieveNeighborsForIndex returns?

Is there a chance that the result of this method is retained (not autoreleased)?


arrayWithArray retains the objects that you stored into your mutable array. http://www.iphonedevsdk.com/forum/iphone-sdk-development/14285-nsmutablearray-arraywitharray-does-add-retain.html

I would recommend releasing it, or safer yet create the objects with the autorelease attribute set. When calling retrive neighbors for index make those objects autorelease and they will be released when the nsmutable array is dealloc'ed

EDIT: One Tip I might add when tracking down memory bugs is to enable zombies, and check the reference count of your objects. You can then determine which ones are not being released and it should make your tracking easier. This link will show you how to setup your xcode project to enable zombies: cocoadev.com/index.pl?NSZombieEnabled

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜