Re: NSXMLParser frees itself on error?
Re: NSXMLParser frees itself on error?
- Subject: Re: NSXMLParser frees itself on error?
- From: Marcel Weiher <email@hidden>
- Date: Wed, 6 May 2009 22:27:04 -0700
On May 6, 2009, at 21:34 , Jeff Johnson wrote:
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.
OK, quiz time: the reason for NSMutableString to relinquish ownership
is to (a) release the object (b) allow someone else to take ownership?
The documentation is absolutely, unmistakably, crystal clear on
this: "You do not own objects returned from convenience
constructors, or from other accessor methods."
EXACTLY. Autorelease allows ownership transfer from called methods to
occur without thrusting ownership on those that don't want it.
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.
Some claim, many dispute. Wether it is 'preferred' or not, however,
is irrelevant to what I said: it is not required and thus there is no
need to do this. Alas, misunderstandings such as yours are exactly
the sort of thing I foresaw when I co-wrote "Autoreleasing accessors
considered harmful"
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.
This is not a debate. This is me explaining to you how this stuff
works.
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.
Wether it passes the values up or not is not the point. The point is
that you don't have any guarantee as to the lifetime of objects after
your method has returned unless you own it, and you will not find such
a guarantee in the docs.
The point is that the callee is not responsible for worrying about
what the caller will do with the objects.
Sort of. The callee does not worry about this because it is
completely out of his control. You do not get any guarantees.
If the callee ensures that the object remains valid within the
caller's scope,
The callee cannot actually ensure this without owning the object. The
wording in the docs is a little sloppy at this point. What it
"ensures" is that it remains valid until it gets to the callers scope,
and anyway, this is a guarantee for the *caller* not for the
*callee*. The callee does not get any guarantees in this model except
that the object will reach the caller.
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?
Exactly.
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.
Yes, we need to be somewhat careful, which is why don't do crazy stuff
like releasing an object from within a delegate method.
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.
No, this is not 'weird' at all. In fact, NSXMLParser very likely
*should* maintain autorelease pools, because its clients can't safely
do this and there is quite a potential for growing the heap during XML
parsing.
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.
Well, I've been doing it for maybe 15 years and it never seemed
particularly hard to me.
You'll end up writing crazy, inelegant, hard to read, hard to
understand code.
What's crazy and weird about:
id parser = [NSXMLParser alloc] initWithData:myData];
[parser parse];
[parser release];
?
Trying to deallocate an object from within its delegate, now that's
weird and crazy, as numerous people have pointed out to you.
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?
The delegate never has 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.
The only thing that would be weird here would be if the caller were
actually deallocated when it returns from sending the "didFinish"
message. Look at the following.
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?
It is the *owner* of the object that releases it, not the delegate.
Anyway, various people have now tried to explain to you how this stuff
works and the fact that the docs do not say what you think or would
like they say. Debating with us doesn't change the code or how it
works.
Cheers,
Marcel
_______________________________________________
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