Re: Memory allocation questions
Re: Memory allocation questions
- Subject: Re: Memory allocation questions
- From: Raphaël Delcroix <email@hidden>
- Date: Wed, 31 Jul 2002 01:02:35 +0200
return to the past...
>
>> so that if they are in the autorelease pool when you get access to
>
>> them, you can make sure they stay around until you're done with them.
>
>
>
> This has nothing to do with autorelease pools. Please don't make it
>
> more complicated than necessary.
>
>
>
> You want to keep it, you send it retain. That's it.
>
>
Right. I should have something more like... "Sending a retain or a copy
>
guarantees that the object will be around for you until you release it,
>
unless someone mistakenly sends more release or autorelease messages
>
than they should to the object."
>
>
The allocation pools are *only* used by autorelease, right?
>
>
I'm trying to keep it simple, but I'd like to understand the details. :)
>
As I like to understand the details, and as it often helps a lot to
examine sources, I advise you to have a look at :
ftp://ftp.gnustep.org/pub/gnustep/core/
(found in :
Date: Fri, 08 Feb 2002 21:56:09 -0800
Subject: Re: Why Cocoa source code isn't open? [terribly OT]
From: Zac Belado <email@hidden>
thanks to him)
It gives the sources of the GNUStep version of the Cocoa framework.
As we are not yet hired by Apple, we cannot be sure the implementation
is the same.
However, it shows how it **could** be implemented.
As I discovered it today, I've tried to clarify all this memory stuff,
especially about autorelease pools...
You'll see it is very simple :
(copy this in Project Builder :)
// In GNUStep, the reference count is increased only when the object is
// retained (or so) => this is not a reference counter, but a retain
counter
// => the object is dealloc'd if the 'retained' counter == 0.
/*************************************************************************
****/
// In Mac OS X Cocoa, it seems that the creation sets the ref count to 1.
// I modified everything to make it clear and conform to the OS X
behaviour
// (and simplified a lot !)
// I made as if the ref count was an instance variable (refCount) of
NSObject.
// (and so on...)
// Here is what could be a simple NSObject and NSAutoreleasePool
implementation :
/*(I think I'm going to get killed for what I'm doing now, but if it can
help...)*/
/*(And as it may be full of errors, as I'm not (-: hum, yet :-) a
specialist...)*/
/*(Another thing : as in GNUStep, it is mixed C and Cocoa)*/
@implementation of a pseudo NSObject
+ (id)alloc {
return [self = alloWithZone:nil];
}
+ (id)allocWithZone:(NSZone *)zone {
// do all the stuff :-)
self->refCount = 1;
return self;
}
- (void) dealloc {
// end all the stuff...
}
- (id) retain { // and idem for (mutable)copy
(self->refCount)++;
}
- (void) release {
if (--(self->retained) == 0)
[self dealloc]
}
- (void) autorelease {
[current_autorelease_pool addObject(self)];
// yeah ! it is brute simplification ! (and omniscience for this
object !)
}
@end
@implementation of a pseudo NSAutoreleasePool
// if you look at Apple's NSAutoreleasePool.h, you'll see it is very
mysterious and...
// reserved... :-)
/*(it is not criticism)*/
- (id) init {
// 1. allocate a chained list in memory to contain the references to
the
// autoreleased objects :
_released = (struct autorelease_array_list*)
NSZoneMalloc(NSDefaultMallocZone(),
sizeof(struct autorelease_array_list)
+ (BEGINNING_POOL_SIZE * sizeof(id)));
/* Currently no NEXT array in the list, so NEXT == NULL. */
_released->next = NULL;
_released->size = BEGINNING_POOL_SIZE;
_released->count = 0;
// 3. install itself as the current pool
etc...
return self;
}
- (void) addObject:(id)anObject {
// add the object at the end of the list
// => the same object can be recorded several times here
_released->objects[_released->count] = anObj;
(_released->count)++;
}
- (void) dealloc {
// release each object of the chained list :
while (released)
{
for (i = 0; i < released->count; i++)
{
id anObject = released->objects[i];
released->objects[i] = nil;
[anObject release];
}
released->count = 0;
released = released->next;
}
}
/****************************************************************/
Practical example :
. I called the object itself myObject (b the pointers o, o2, o3...)
.
method1 :
o = [[alloc] init]; b> (o -> myObject) : refCont = 1
return [o autorelease]; b> pointer to myObject simply (p1) stored in
the autorelease list !
=> nothing has changed for our object and for refCont !!!
(isn't it clear like that ?)
method2 (which receives the value) :
o2 = [self method1]; b> 'o2' -> myObject (the label 'o' is
out of C scope)
return o2; (this method has no ownership)
method3 (which receives the value) :
o3 = [self method2]; b> 'o3' -> myObject (the label 'o2' is
out of C scope)
[o3 retain]; b> myObject.refCont = 2
return [o autorelease]; b> pointer to myObject (p2) stored a second
time in the autorelease list !
end of the current event processing :
(in the dark realm of the Cocoa in action :)
[currentAutoreleasePool release]
in the currentAutoreleasePool object :
[... release];
[p1 release]; b> myObject.refCont = 1
(...)
[p2 release]; b> myObject.refCont = 0 : call to
dealloc !
/*****************************************/
Now, if the object was retained and stored by a method4 in an (instance)
array :
(say the current event processing is not finished : we go back to
method3)
method4
o4 = [self method3]; b> 'o4' -> myObject (label 'o3' out of
C scope)
[[self myArray] addObject:o4];
b> in the less strange realm of
NSArray :
[o4 retain] stored.
b> myObject.refCont = 3
return;
the method returns to the dark caller (action method for example)
= end of the current event processing (which has triggered our action
method)
(if there are no embedded autorelease pool, of course)
[currentAutoreleasePool release]
in the currentAutoreleasePool object :
[... release];
[p1 release]; b> myObject.refCont = 2 now !
(...)
[p2 release]; b> myObject.refCont = 1 : the object is
still alive !!!
the user quit this single-class application :
in dealloc :
[myArray release]; b> in the realm of the NSArray mechanism :
all objects are released
[(myObject *) release];
b> myObject.refCont = 0 : the
object is dealloc'ed !
That's all folks !
I'm very sorry for this very long response, but I think it can help a
lot.
Don't hesitate to tell me if I'm wrong about something !
R.D.
N.B. thank you for all members of the GNUStep project, without whom I
couldn't have written all that !
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.