Re: NSXMLParser frees itself on error?
Re: NSXMLParser frees itself on error?
- Subject: Re: NSXMLParser frees itself on error?
- From: Jeff Johnson <email@hidden>
- Date: Wed, 6 May 2009 23:34:56 -0500
On May 6, 2009, at 9:38 PM, Marcel Weiher wrote:
On May 6, 2009, at 18:45 , Jeff Johnson wrote:
I think you misunderstand the problem that autorelease is trying
to solve, which is to allow ownership transfer from a callee back
to its caller, not to just simply delay a release until "later".
Ownership 'transfer' is rare. If you call +alloc or -copy, for
example, ownership is transferred to the caller. Otherwise, there's
no such thing.
The fact that you think this is a testament to how well -autorelease
works :-)
How about +[NSMutableString string] ? Do you think the
NSMutableString class keeps ownership of the array you have created?
No, the NSMutableString class relinquishes ownership. But this does
not mean that the caller acquires ownership. The documentation is
absolutely, unmistakably, crystal clear on this: "You do not own
objects returned from convenience constructors, or from other accessor
methods."
<http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.html#//apple_ref/doc/uid/TP40004447-SW2
>
This is why you can't implement your getters as -(id)myThing
{ return [_myThing retain]; }. When someone else calls -myThing,
you still own the object, which is why you're responsible for
balancing out the retain with an autorelease. You call release or
autorelease on an instance variable to relinquish ownership of the
object, not to 'transfer' ownership.
This is largely incorrect. There is no need for an -autorelease in
a getter, just like there is no need for the retain. *If* you do a
retain, for whatever reasons, then you need to balance it with a
release or an autorelease.
Retain/autorelease is the preferred way of implementing a getter
method. This guarantees the validity of the object in the caller's
scope: "Because it may not always be obvious when a caller should
retain an object in this manner, the objects themselves should strive
to return results that are valid in the current calling scope."
<http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmObjectOwnership.html#//apple_ref/doc/uid/20000043-1000922
>
The *only* reason not to use retain/autorelease is if the getter is
being called millions of times rapidly, and performance becomes an
issue.
It is perfectly safe to use autorelease for the things it was
intended for. It never was safe for the things you seem to want to
use it for.
Nope, wrong.
Nope.
You need to re-read that document, because it does not say what you
think it says.
I can't argue against these statements, because you've offered no
argument in favor of them, so I'll just ignore them.
"When another method gets the array of Sprocket objects, that
method can assume that the array will be disposed of when it is no
longer needed, but can still be safely used anywhere within its
scope (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."
This does not say that you (the callee) can tunnel through the
caller. It say that the caller can, at its discretion, decide to
pass the objects up to its caller. However, it does not have to do
this.
http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmObjectOwnership.html#/
/apple_ref/doc/uid/20000043-1000922
"Cocoa’s ownership policy specifies that received objects should
remain valid throughout the scope of the calling method. It should
also be possible to return a received object from the current scope
without fear of it being released."
That is: there is nothing that Cocoa does to make the object go
away during the scope of the calling method. However, the calling
method certainly has the freedom to make the objects go away.
From the callee's perspective, a call to autorelease defers the
release until the end of the event loop.
That is completely wrong. Wherever you got that information from,
forget it, delete it, purge it, unremember it.
Heh, I can't very well delete Apple's documentation. "The
autorelease method, defined by NSObject, marks the receiver for
later release."
Yes, but you don't get to say how much later. Your caller does.
In response to this last argument (which is essentially the same in
the three 'sections' immediately above): it's certainly true that the
caller doesn't need to pass objects up to its own caller; indeed, this
is not even possible if the caller has no return value. The point is
that the callee is not responsible for worrying about what the caller
will do with the objects. If the callee ensures that the object
remains valid within the caller's scope, that's the extent of its
memory management job. It would be hard to do any more. How is the
callee supposed to know when the caller is done with the object?
Now, in this particular case I don't think it's acceptable to take the
dogmatic attitude that the caller has the right to do whatever it
wants with the objects, because we have a bit of an unusual situation
here, involving a weak reference. The delegating object cannot have a
strong reference to its delegate, otherwise you'd have a retain cycle.
The rules of memory management that apply to strong references don't
fully apply here, we need to be very careful.
My view, to put it somewhat casually, is that in 'odd' situations such
as this, object encapsulation is best served by having the object
that's using unusual memory management techniques take responsibility
for not screwing things up. In standard code, you have one main
autorelease pool for the main thread, which is either automatically
created by AppKit or, in a Foundation tool, you create at the
beginning of main() and destroyed at the end. If you have threads,
each thread has one main autorelease pool created at the beginning and
destroyed at the end. Other than that, it's unusual to create your own
pools. You may do it in a tight loop to keep memory from ballooning.
It's really a rare and weird situation where you're creating a pool
and then calling methods on your object's weak-referenced owner.
To me, it's madness to say that it should be standard practice to
design an object around the possibility that an object it owns (strong
reference) may create these rare and weird autorelease pool situations
and possibly cause its own deallocation in mid-method. It's really
hard to design an app around that idea. You'll end up writing crazy,
inelegant, hard to read, hard to understand code. It makes much more
sense to code in a more straightforward way, for the common case, and
if an object is going to do weird memory things with its delegate, it
needs to take responsibility for not causing crashes and other
problems. In this case, the delegating object knows when it's going to
wrap the delegate calls in an autorelease pool, so it can easily
account for that, whereas the delegate itself has no idea and would
have a very hard time accounting for that. How does the delegate know
when exactly in the future it's safe to actually release or
autorelease its instance variable? You might say wait until dealloc,
but it may need to re-use that instance variable for another object.
I'm not sure I understand what the alternative is that you're
suggesting. Short of dealloc, when exactly is it safe for the delegate
to relinquish ownership of the object? According to your argument, you
can't even assume it's safe in some kind of "didFinish" delegate
method, because the object could still do weird stuff after calling
didFinish on the delegate. It's of course somewhat easier to work
around this problem given the API of NSXMLParser, but you can't
generalize to all delegate methods based on NSXMLParser. What about
more async delegate like NSURLConnection?
-Jeff
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden