memory leak when adding objects to nsarray

2019-07-25 13:19发布

问题:

In the code below, PersonListArray is an NSMutableArray and I'm getting the list of persons from the sqlite DB and adding it to my array.

Person* tmpPerson = [[Person alloc] init];
tmpPerson.personName = @"Mike";
tmpPerson.personEmail = @"mike@mike.com"; 

[PersonListArray addObject:tmpPerson];
[tmpPerson release];

Even though I'm releasing the Person object here, its giving a memory leak which I'm guessing is due to the array holding a reference count to it. I'm using the array elsewhere in the program and then releasing it for sure.

What's the best practice to create new objects for an array and not run into this issue?

In the dealloc method where i release the array

-(void) dealloc{
  [PersonListArray release]; // this contains the numerous Person objects
  [super dealloc];
}

should i manually release them like this instead ?

-(void) dealloc{

   for (int i = 0; i<PersonListArray.count;i++)
   {
     Person * tmpPerson = [PersonListArray objectAtIndex:i];
     [tmpPerson release];
   }

  [PersonListArray release];
  [super dealloc];
}

回答1:

Your code, as initially implemented, is correct. An array retains onjects added to it and releases them either when they're removed from the array or when the array is dealloced. No need to go through the array yourself.

What means are you using to detect the leak? If it's Instruments then you may be misunderstanding what it is telling you. When it detects a leak, it can show you where the memory was first allocated. It can't show you which object is responsible for the leak. I would therefore guess the given dealloc method is never called (because that object is leaked) or that someone else retains the array and doesn't release it. Try putting an NSLog in dealloc to ensure that it is occurring; as a run once test you could try logging PersonListArray after releasing it — if that doesn't cause a memory exception then almost certainly someone else has retained it.

[REMOVED: my original text "Try adding an NSLog of [PersonListArray retainCount] to your dealloc to figure out which is the case."; see comment from bbum below]

The most common cause of accidental additional retains is @property/@sythesize properties that are set to retain but for which a matching release is not added to dealloc.



回答2:

The code you are showing us is correct and contains no leaks. The last section is wrong, though, and would case your program to crash because you are releasing Person objects you no longer own.



回答3:

Somewhere else in your app, you probably call [PersonListArray objectAtIndex:n] and pass it around to various other parts of your app. One of the other parts of your app is probably leaking it.

If you're using leaks, click on the particular "type of leak", then click on the memory address, and it'll show you the alloc/free/retain/release/autorelease history of that memory address. If you enable the detail view (Cmd-E I think), you'll see stack traces for all of those as well. Look for something that's doing a retain but not a corresponding release. (It's a bit difficult when things are retained by multiple autoreleased arrays...)