0

Possible Duplicate:
Objective C Memory Management

My code is showing a memory leak here:

NSMutableArray* newImageArray = [[NSMutableArray alloc] init];
NSMutableArray* newMediaArray = [[NSMutableArray alloc] init];

if (self.categoryIndex == 0) {
    for (int i=1; i < [categoryArray count]; i++)
    {
        newImageArray = [NSMutableArray arrayWithArray:[newImageArray arrayByAddingObjectsFromArray:[self getImageArrayByCategoryIndex:i]]];
    }
}
else {
    newImageArray = [self getImageArrayByCategoryIndex:self.categoryIndex];
}

for (int i=0; i < [newImageArray count]; i++)
{
    Media* media = [[Media alloc] init];
    NSString* imageFile = [newImageArray objectAtIndex: i];

    media.imageFile = [UIImage imageNamed:imageFile];
    media.imageLabel = [[imageFile lastPathComponent] stringByDeletingPathExtension];
    media.soundFile = [appFolderPath stringByAppendingString:[[[imageFile stringByDeletingPathExtension] stringByAppendingString: @".wav"] stringByReplacingOccurrencesOfString: IMAGES_FOLDER withString: SOUNDS_FOLDER]];

    [newMediaArray addObject:media];
}

self.mediaArray = newMediaArray;

[self setNextMediaIndex];

I am not releasing media because it is being used by newMediaArray (which is used by mediaArray, which is used my my main object). Shouldn't everything get released when I release my main object?

Community
  • 1
  • 1
user472292
  • 1,069
  • 2
  • 22
  • 37
  • 1
    Welcome to StackOverflow. Why not choose a user name and make yourself comfortable? Also, just post this code as an edit to your other question. – Moshe Aug 14 '11 at 16:35
  • In the `if` branch, you are not adding objects to the original `newImageArray`, you are replacing it entirely with another array in each iteration of the `for` loop, leaking the original array (the others are autoreleased). You probably want `[newImageArray addObjectsFromArray:...];`. The `else` branch also leaks the original array since you assign a different array. In the second `for`, you leak the `Media` object in every iteration. After `self.mediaArray = newMediaArray;` you don't release `newMediaArray` either. – albertamg Aug 14 '11 at 16:58

4 Answers4

1

It looks like you are leaking all over the place in a variety of ways

newImageArray gets allocated but never released, additionaly you are overwriting the version that you allocated in the first line of you code with another version. So even if you released it at the end of this code segment, the wrong version would get released. It looks like you don't even need to allocate this one.

newMediaArray gets allocated but never released, you assign it to a property mediaArray if you are using @synthesize to create the code for that property, depending on how you declared that property, the setter will retain the value i.e. newMediaArray creating a leak.

media gets allocated but never released, it get added to a NSMutableArray which means it will get retained by the array. If your app crashes when you release media in the for loop the problem is somewhere else

The Memory Management Programming Guide is pretty much a must read

Harald Scheirich
  • 9,676
  • 29
  • 53
0

When an NSMutableArray such as newMediaArray adds an object, it will retain that object. You don't need to (nor should you) retain the object on the array's behalf. This is fundamentally how memory management in Objective-C works: each object retains the things it references, and releases them when finished. newMediaArray is its own object, so it'll manage its own references.

You should release media near the end of the body of your for loop because you're done using that object. If you don't release it then, you'll lose your reference to it and you'll have no way to release it in the future.

Caleb
  • 124,013
  • 19
  • 183
  • 272
0

You do

[newMediaArray addObject:media];

that means that newMediaArray has done a retain on media. You can then release media (you should). The retain done in the array method will keep it alive as long as the array references it. If you don't release it in your method, the retain count will remain 2, and even if the array releases it, it will still be 1 and not be dealloc-ed.

You could do:

Media *media = [[[Media alloc] init] autorelease];

Then the autorelease pool will release it in time, but not before this method ends.

Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94
0

You need to have the [media release] statement at the bottom of the loop. newMediaArray should also be released after it is assigned to the mediArray property.

Dmitry S.
  • 8,373
  • 2
  • 39
  • 49