Re: NSAttributedString crashes
Re: NSAttributedString crashes
- Subject: Re: NSAttributedString crashes
- From: Quincey Morris <email@hidden>
- Date: Thu, 03 Mar 2011 11:24:08 -0800
On Mar 3, 2011, at 10:10, Matt Neuburg wrote:
> What you *can* rely on is that a ***factory method*** will hand you an autoreleased object. So, [NSArray array] hands you an autoreleased array; it won't vanish right this second, but it will vanish when your code comes to an end, unless you retain it. You may be confusing this with that. Even in that case you don't have ownership; you just have some extra persistence time while your code continues to run. And this makes sense, because there is no other owning object.
EXCEPT:
What you say can't be literally true. In the non-factory-method case of a returned property value, you *do* have some extra persistence time, because you *must* have some extra persistence time, because you need to be able to retain the returned value before it disappears:
id someValue = [someObject someProperty];
[someValue retain]; // someValue must persist at least this long
Of course, in the simplest case where multiple threads aren't involved, this looks safe enough, because nothing should cause 'someValue' to dealloc before the retain.
So, the question arises: how long are you permitted to go before you need to do the retain? AFAIK there's no actual answer to that question, but the pragmatic answer has always been: until the next drain of an autorelease pool that might contain the object (that is, often, until you return to the main event loop), and that's a little hard to predict in the general case that might involve local autorelease pools.
What I'm trying to say is that deciding whether to be "safe"/"tedious" is, theoretically, guesswork. In practice, the usual heuristic is to assume a retained-autoreleased object, and to fix the crashes on a case by case basis -- which is what Gerriet just had to do.
EXCEPT:
> Suppose you've got an NSArray and you fetch its element objectAtIndex:0. And suppose you now let go of the array (release) and it is destroyed. Do you expect the fetched element to persist without your having retained it? You do not; you know darned well that a collection doesn't behave like that. The collection *owns* its elements and will release them when it is released. All you got when you called objectAtIndex:0 was a pointer. If you want a share in its ownership, you must *take* ownership.
And the one common zero-extra-persistence-time case that you didn't quite mention:
id someValue = [someArray objectAtIndex: 0];
[someArray removeObjectAtIndex: 0];
[someValue retain]; // too late!
I think both of these are essentially different from Gerriet's case, because there is an obvious change-of-ownership "event" between getting the non-retained pointer and retaining it. The only real connection between the two scenarios is that you end up with a pointer to a possibly dead object, unless you take care.
AND:
Things are both better and worse under garbage collection. Worse, because there is no extra persistence time, because the GC thread could run at any moment. Better, because the the compile-time scoping of variables *usually* creates the effect of extra persistence time, until the run-time equivalent of the "}" of the block containing their declaration. Except when optimization shortens the effective scope. But that's a different discussion.
_______________________________________________
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