Re: Memory allocation questions
Re: Memory allocation questions
- Subject: Re: Memory allocation questions
- From: Nathan Day <email@hidden>
- Date: Sun, 28 Jul 2002 15:51:57 +0930
On Sunday, July 28, 2002, at 02:22 PM, Terry Simons wrote:
"By autoreleasing an object-that is, by sending it an autorelease
message-you declare that you don't need the object to exist beyond the
scope you sent autorelease in."
I'm assuming that scope here means essentially the same thing as in
standard C/C++? If I declare something in a method, it dies at the end
of the method's scope, and you should release any memory you've
allocated in the method?
Essentially yes, the object is actually release when then autorelease
pool is released, which is usually at the end of the current event loop.
Ok, so autorelease is called. We use autorelease in this instance so
we're not destroying the data before it reaches the calling code,
correct? Essentially, a "release" here would deallocate the memory
that array was pointing at, correct? We don't want that, so we
autorelease.
What *exactly* does autorelease do differently than release?
There is an object like an NSArray called NSAutoreleasePool, it's in the
docs, which autorleased objects are added to, when NSAutoreleasePool is
released, an retain count is then 0, it tells all of the objects that
have been added to it to release. So autoreleasing means call the
release method sometime later.
Does it play with the counter that determines when to release an
object? Does it do more?
The next paragraph from the docs:
"When another method gets the array of Sprockets, that method can
assume that the array will be disposed of when it's no longer needed,
but can still be safely used anywhere within its scope (with certain
exceptions; see "Validity of Shared Objects" ). It can even return the
array to its invoker, since the application object defines the bottom
of the call stack for your code. The autorelease method thus allows
every object to use other objects without worrying about disposing of
them."
Now... does this NSArray get disposed of at the end of the scope of the
function it got returned to, or does it live for the life of the
application?
At first glance, I would assume that it is for the life of the method
scope. "...that method can assume that the array will be disposed of
when it's no longer needed, but can still be safely used anywhere
within its scope..." Which goes back to my question of whether
"scope", in this case, is the scope of the method, as it would be in C,
or if it's something specific to ObjC. Does it mean application
scope? The next thought from the above paragraph confuses me:
I think it means method scope in that next time the method is called the
object is assumed to no longer exist. Autorelease pool isn't a part of
the language, its a part of cocoa, so it doesn't know about method
scope. Some where down at the base of all these calling methods is
something like
pool = [[NSAutoreleasePool alloc] init]
// your nested calling methods
[pool release];
you can't return objects out of this release pool, if you created your
own NSAutoreleasePool, some where and you wanted to return object from
it you would have to call autorelease for those objects after the [pool
release] where they would get added to a NSAutoreleasePool lower down.
"It can even return the array to its invoker, since the application
object defines the bottom of the call stack for your code. The
autorelease method thus allows every object to use other objects
without worrying about disposing of them."
What does the term "invoker" mean in this sentence? "since the
application object defines the bottom of the call stack for your code"
also confuses me.
That's why I asked above if the object lives for the life of the
application, though I don't think that's right...
A NSAutoreleasePool is created at the beginning of every run loop and
then released at the end of the runloop, so life time is the life of the
current runloop.
Now... if I did return this array again, would I have to issue a retain
when I return the object? If the object lives in method scope only,
then it would seem so.... because if autorelease works the way I think
it does, then after each "scope hop" the counter for the object in the
release pool gets decremented? If not, can someone explain what
autorelease does?
No.
If it does get decremented at each scope hop, then a retain would be
necessary for each "return"? So.... return [array retain];?
But would you have to autorelease it again? So.... return [ [array
retain] autorelease];? (That seems awfully redundant)
No
I'd like to get a firm understanding of how this stuff works before I
jump in with both feet. :)
I'm also confused about the retain, and autorelease in the following
method, also an example in the docs:
- (void)setMainSprocket:(Sprocket *)newSprocket
{
[mainSprocket autorelease];
mainSprocket = [newSprocket retain]; /* Claim the new Sprocket. */
return;
}
My attempt at understanding the above method:
First Line:
mainSprocket needs to get autoreleased because we're going to change
it's value? (Why not use release instead of autorelease in this
example?)
You could, I don't know why they choose to do it that way, but it just
means it gets released latter on which is not a great deal more over
head.
Second Line:
mainSprocket gets newSprocket, retain the contents, because the
function that passed in the data should have autoreleased it?
Its not necessarily autoreleased, it's just that you don't want to have
to rely on somebody else retaining the object for you, when they choose
to release it is there business and you should not depend on that. A
thing you have to watch though is circular retains, if two objects have
references to each other who should retain whom, if they both retain
each other they neither will get released, if they release each other in
their dealloc methods. usually it easy to see who should do the
retaining from the design of your app, who owns the other object, who
just has a reference to it's owner.
One more:
- (void)setMainSprocket:(Sprocket *)newSprocket
{
[mainSprocket autorelease];
mainSprocket = [newSprocket copy]; /* Get a private copy. */
return;
}
I'm assuming that mainSprocket is basically getting a copy of all of
the values stored in newSprocket?
This seems like a (sorry for likening this to another language) C++
copy constructor. Is that a close approximation?
Yep it sort of like C++ copy constructor, it just return a copy so you
can modify it with out messing it up for anybody else who has a
reference to the object, this is a design decision should everybody
modify the same object or should they have their own copy. Though
sometime copy will just retain the object, if the object can't be
modified then it doesn't make any difference and create more than one
copy is just a waste of memory
Ugh... this stuff makes my brain hurt.
autoreleased objects are simply objects that will be released sometime
later on outside of the scope of your nested stack of calling methods.
Nathan Day
http://homepage.mac.com/nathan_day/
_______________________________________________
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.