I'm doing my last bit of memory management tidying and there's something I don't understand. I've checked all the documentation, Stack Overflow, etc. but still don't get it. I suspect it's to do with arrays.
I have an NSMutableArray
开发者_运维百科 as an instance variable which I use to hold objects created from objects in another array.
-viewDidLoad
initialises the array as follows:
self.photoAlbum = [[NSMutableArray alloc] initWithCapacity:100];
It then calls a method which populates them.
int i = 0;
for (Gem *gem in self.entityArray) {
NSString * filePath = [[NSString alloc] initWithFormat: @"%@/%@2.jpg", [sysPaths objectAtIndex: 0], gem.detailsTitle];
// there is some stuff in here that means that there isn't a one to one relationship between the objects in gem and those in photo
Photo *photo = [[Photo alloc] init];
photo.filePath = filePath;
photo.title = gem.title;
photo.index = [NSNumber numberWithInt:i];
[self.photoAlbum addObject:photo];
[filePath release];
[photo release];
i++;
}
In Instruments, it shows I'm leaking Photo
objects and I'm not sure why.
The photoAlbum
property is:
@property (nonatomic, retain) NSMutableArray *photoAlbum;
What am I missing?
The problem is that the setter of your property has retain
semantics. You need to autorelease
when you are setting the property, like so:
self.photoAlbum = [[[NSMutableArray alloc] initWithCapacity:100] autorelease];
or, even better:
self.photoAlbum = [NSMutableArray arrayWithCapacity:100];
The reason this is the case is that the setter you've generated by synthesizing that property looks something like this (simplified):
- (void)setPhotoAlbum:(NSMutableArray *)array {
[photoAlbum autorelease];
photoAlbum = [array retain];
}
So, what is happening is:
[photoAlbum autorelease];
photoAlbum = [[[NSMutableArray alloc] initWithCapacity:100] retain]; // 0 + 2 = 2
// in -dealloc:
[photoAlbum release]; // 2 - 1 = 1
Hence, photoAlbum
is never released enough times to be deallocated, since -release
looks something like this (heavily simplified):
- (void)release {
retainCount = retainCount - 1;
if (retainCount == 0) {
[self dealloc];
}
}
(I want to reiterate that this is basically what the implementation is doing, but not what it looks like in real life). The point is that you'll not trigger a deallocation until you've balanced your releases against your retains.
Do not take this as an exhortation to EVER look at -retainCount
, ever, ever. Other objects existing at runtime may be retaining your object and doing things with it that you don't know about; therefore, the actual retain count of your object at any given time is useless to you. Please never, ever use it when managing memory. @bbum will thank you.
You are probably missing
[photoAlbum release];
in the dealloc method.
Edit
Actually, I was wrong. The problematic line is
self.photoAlbum = [[NSMutableArray alloc] initWithCapacity:100];
The array you create is one you own, but you don't release it. This will fix it:
self.photoAlbum = [[[NSMutableArray alloc] initWithCapacity:100] autorelease];
精彩评论