 | | From: | Kinou | | Subject: | Release an Object in a collection | | Date: | Wed, 22 Dec 2004 17:09:22 +0100 |
|
|
 | Hello,
I'm trying to make a Stack in Objective-C, and I've got a problem with memory management. When I add an object to my collection, it receives a retain message. That's ok. But when I dealloc my collection (by sending a release message), how can I send a release message to all the objects that were in the collection ?
For example if I use a NSMutableArray like that :
Integer *trois=[[Integer alloc] initWithInt:3];
printf("retain count %d\n",[trois retainCount]);
NSMutableArray* arrayTest = [NSMutableArray new]; [arrayTest addObject:trois]; printf("retain count %d\n",[trois retainCount]); [arrayTest release]; printf("retain count %d\n",[trois retainCount]);
I see : retain count 1 retain count 2 retain count 1
And that's ok, but with my collection I see : retain count 1 retain count 2 retain count 2
The count is always 2 after releasing my collection. Any idea ?
PS : I'm french, so sorry for my poor english ...
-- Regards, Vincent JOUSSE
|
|
 | | From: | Sherm Pendley | | Subject: | Re: Release an Object in a collection | | Date: | Wed, 22 Dec 2004 12:56:02 -0500 |
|
|
 | Kinou wrote:
> I'm trying to make a Stack in Objective-C
Tilo has already given one good answer, but here's another possibility.
A stack is really just an array with push and pop methods, so have you considered simply adding -pushObject: and -popObject methods to NSMutableArray with a Category?
@implementation NSMutableArray (MyStackMethods)
- (void) pushObject: (id)theObject { [self addObject:theObject]; }
- (id) popObject { id theObject = [self lastObject]; [self removeLastObject]; return theObject; }
@end
sherm--
-- Cocoa programming in Perl: http://camelbones.sourceforge.net Hire me! My resume: http://www.dot-app.org
|
|
 | | From: | Michael Ash | | Subject: | Re: Release an Object in a collection | | Date: | Wed, 22 Dec 2004 12:20:25 -0600 |
|
|
 | Sherm Pendley wrote: > Kinou wrote: > >> I'm trying to make a Stack in Objective-C > > Tilo has already given one good answer, but here's another possibility. > > A stack is really just an array with push and pop methods, so have you > considered simply adding -pushObject: and -popObject methods to > NSMutableArray with a Category? > > @implementation NSMutableArray (MyStackMethods) > > - (void) pushObject: (id)theObject { > [self addObject:theObject]; > } > > - (id) popObject { > id theObject = [self lastObject]; > [self removeLastObject]; > return theObject; > } > > @end
Better write popObject like this:
- popObject { id theObject = [[[self lastObject] retain] autorelease]; [self removeLastObject]; return theObject; }
If you don't do the retain/autorelease pair, then the object will be destroyed if it's not retained elsewhere, and you'll probably tear your hair out trying to find the problem.
|
|
 | | From: | David Stes | | Subject: | Re: Release an Object in a collection | | Date: | Wed, 22 Dec 2004 21:06:41 GMT |
|
|
 | Michael Ash wrote: > Better write popObject like this: > > - popObject { > id theObject = [[[self lastObject] retain] autorelease]; > [self removeLastObject]; > return theObject; > }
This is wrong; the -retain should be done by the method that uses -popObject.
[[someStack popObject] retain];
With your implementation, you will leak memory.
> > If you don't do the retain/autorelease pair, then the object will be > destroyed if it's not retained elsewhere, and you'll probably tear your > hair out trying to find the problem.
Yes, but the alternative, of leaking memory, although slightly better (no immediate crash) will eventually also result in a crash (due to leak)
|
|
 | | From: | Sherm Pendley | | Subject: | Re: Release an Object in a collection | | Date: | Wed, 22 Dec 2004 17:05:05 -0500 |
|
|
 | David Stes wrote:
> Michael Ash wrote: > >>Better write popObject like this: >> >>- popObject { >> id theObject = [[[self lastObject] retain] autorelease]; >> [self removeLastObject]; >> return theObject; >>} > > > This is wrong; the -retain should be done by the method that uses -popObject. > > [[someStack popObject] retain]; > > With your implementation, you will leak memory.
Utter nonsense - as is normal for David Stes. Neither my broken original nor Michael's correction leaks.
Michael is right, retain/autorelease should be done within -popObject, I'd overlooked that.
The problem with my original code - which David's "correction" does not fix, but Michael's does - goes as follows:
id theObject = [self lastObject]; // theObject points to // the last object. (duh)
[self removeLastObject]; // The last object is removed // *and* *released* // theObject now points to an // object that has been released
return theObject; // An invalid object reference is // returned - it's too late to // fix the problem by retaining // it in the caller.
Michael's fix causes the object to go into the autorelease pool, so when it's removed from the array there's still at least one reference to it, so it won't be immediately dealloced. It might still be dealloced later, but the pool gives the caller a chance to retain the object before then if it wants.
sherm--
-- Cocoa programming in Perl: http://camelbones.sourceforge.net Hire me! My resume: http://www.dot-app.org
|
|
 | | From: | Tilo_Prütz | | Subject: | Re: Release an Object in a collection | | Date: | Wed, 22 Dec 2004 17:27:52 +0100 |
|
|
 | Kinou wrote:
> Hello, > > I'm trying to make a Stack in Objective-C, and I've got a problem with > memory management. > When I add an object to my collection, it receives a retain message. > That's ok. But when I dealloc my collection (by sending a release > message), how can I send a release message to all the objects that were > in the collection ? >
Have I understood you correctly? You implemented your own collection, right? So you are sending retain to newly added objects, right?
Then on dealloc you have to iterate over all objects in your collection and send them a(n) (auto)release.
greetz
>tilo
|
|
 | | From: | Kinou | | Subject: | Re: Release an Object in a collection | | Date: | Wed, 22 Dec 2004 17:41:30 +0100 |
|
|
 | Tilo Prütz wrote: > > > Have I understood you correctly? You implemented your own collection, > right? So you are sending retain to newly added objects, right? >
Yes that's right.
> Then on dealloc you have to iterate over all objects in your > collection and send them a(n) (auto)release. >
So I have to implement my own dealloc method, iterating over all the objects ? It seems to be obvious in fact ...
> > greetz >
Thanks !
-- Regards, Vincent JOUSSE
|
|
 | | From: | Tilo_Prütz | | Subject: | Re: Release an Object in a collection | | Date: | Wed, 22 Dec 2004 20:04:11 +0100 |
|
|
 | Kinou wrote: > > So I have to implement my own dealloc method, iterating over all the > objects ? It seems to be obvious in fact ... >
Of course. You retained them so you have to release them.
greetz
>tilo
|
|