开发者

NSMutableArray Instance Variable Memory Management

开发者 https://www.devze.com 2023-02-21 23:55 出处:网络
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 w

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];
0

精彩评论

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