• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: NSXMLParser frees itself on error?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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


  • Follow-Ups:
    • Re: NSXMLParser frees itself on error?
      • From: Marcel Weiher <email@hidden>
References: 
 >NSXMLParser frees itself on error? (From: Mike Manzano <email@hidden>)
 >Re: NSXMLParser frees itself on error? (From: Jesper Storm Bache <email@hidden>)
 >Re: NSXMLParser frees itself on error? (From: "Stephen J. Butler" <email@hidden>)
 >Re: NSXMLParser frees itself on error? (From: Jeff Johnson <email@hidden>)
 >Re: NSXMLParser frees itself on error? (From: Marcel Weiher <email@hidden>)
 >Re: NSXMLParser frees itself on error? (From: Jeff Johnson <email@hidden>)
 >Re: NSXMLParser frees itself on error? (From: Marcel Weiher <email@hidden>)

  • Prev by Date: Re: Dynamic Layout
  • Next by Date: catching whitespace with scanner
  • Previous by thread: Re: NSXMLParser frees itself on error?
  • Next by thread: Re: NSXMLParser frees itself on error?
  • Index(es):
    • Date
    • Thread