views:

6699

answers:

6

I have an array NSMutableArray with happy objects. These objects viciously turn on (leak) me whenever I try to clear the array of all the objects and repopulate it.

It's allocated in the init function like so

self.list = [NSMutableArray array];

The different methods I have used to clear it out include:

self.list = nil;
self.list = [NSMutableArray array];

and

[self.eventList removeAllObjects];

Explicitly allocating and releasing the array doesn't work either. The leak ONLY occurs when I try to reset the list.

Am I missing a step when resetting or is this a different problem?

+4  A: 

what does your @property declaration look like? are you synthesizing the accessors? If so, you need @property(retain). I'm assuming that when you say the objects are turning on you, you're referring to a core dump (EXC_BAD_ACCESS).

Elfred
@property (nonatomic, retain) NSMutableArray *list;I do have a synthesize, but the core dump only happens when I try to release the objects manually. What I mean by turning on me is the objects leaking (I think)
how do you know they are leaking? Are you checking instruments\leaks? If you are getting bad accesses, that means you are releasing something that's already dealloced. Leaks are harder to find in the sense that you need to use a tool to catch them (or just see your memory grow).
Elfred
so, if you're doing [list addObject:[[MyObj alloc] init];and later [list removeAllObjects];you're probably leaking. The solution would be to provide a class method that returns an autoreleased object.
Elfred
I am using instruments to monitor leaks. Your suggestion to return an autoreleased object sounds good. Could I add [self autorelease]; to the return statement for my overrided init method to solve this?
It shouldn't be in the init method since it breaks the contract for initialization. The recommended idiom would be smething like:[MyObject object] or [MyObject objectWithProperty:...}and that would do:MyObject (obj = [[MyObject alloc] init]return [obj autorelease];
Elfred
I had a similar problem, I was using assign instead of retain for objects in a user-defined class. Thanks for the suggestion, that would have taken forever to find.
dr_pepper
+5  A: 

Are you referring to the objects in the array leaking?

How are you adding objects to the array? The array will retain them, so you need to autorelease or release them after you've added them to the array. Otherwise after the array is released the objects will still be retained (leaked).

MyEvent *event = [[MyEvent alloc] initWithEventInfo:info];
[self.eventList addObject:event];
[event release];

MyEvent *otherEvent = [[[MyEvent alloc] initWithEventInfo:otherInfo] autorelease];
[self.eventList addObject:otherEvent];
Nathan Kinsinger
- (void)addEventToList:(Event *)inEvent{ [self.list addObject:inEvent]; [inEvent release];}The object passed is created like this [[Event alloc] init];
Whatever is passing inEvent should release it, not the code it's passed to. Releasing an object you don't know the provenance of is bad.
Chris Hanson
I still have a leak every time I try to clear the array. weirdest thing ever. I've got the method that creates the Event releasing it after it is passed. Everything works fine without removing all the objects in the array.
A: 

I'd say I don't really have enough Information here to give you a great answer. Are you saying that the NSMutableArray is still allocated, but empty and doesn't have any objects in it but that the objects once previously in the array are still allocated even though they should be dealloc'd at that point in the app?

If that's the case the array could possibly be empty, but your objects aren't handling the dealloc message sent to them, in which case the objects are still around in memory but not referenced by anything.

I'd say to help you I'd like to know exactly what MallocDebug exactly says is being leaked. Also @Elfred is giving out some good advice in checking your @property method for the array, really it should be retain or copy.

Colin Wheeler
A: 

If the leak only occurs when you try to reset the list, you have someone/something else using those other objects that you just tried to release.

cschreiner
+2  A: 

How did you create the objects that are leaking? If you did something like this:

- (void)addObjectsToArray {

    [list addObject:[[MyClass alloc] init];

    OtherClass *anotherObject = [[OtherClass alloc] init];
    [list addObject:anotherObject];
}

then you will leak two objects when list is deallocated.

You should replace any such code with:

- (void)addObjectsToArray {

    MyClass *myObject = [[MyClass alloc] init];
    [list addObject:myObject];
    [myObject release];

    OtherClass *anotherObject = [[OtherClass alloc] init];
    [list addObject:anotherObject];
    [anotherObject release];
}

In more detail:

If you follow the first pattern, you've created two objects which, according to the Cocoa memory management rules you own. It's your responsibility to relinquish ownership. If you don't, the object will never be deallocated and you'll see a leak.

You don't see a leak immediately, though, because you pass the objects to the array, which also takes ownership of them. The leak will only be recognised when you remove the objects from the array or when the array itself is deallocated. When either of those events occurs, the array relinquishes ownership of the objects and they'll be left "live" in your application, but you won't have any references to them.

mmalc
A: 

Are you releasing every object inside the array ?, could You post more code ?

José Joel.