Re: How do I debug weak_unregister_no_lock?
Re: How do I debug weak_unregister_no_lock?
- Subject: Re: How do I debug weak_unregister_no_lock?
- From: Greg Parker <email@hidden>
- Date: Wed, 15 Jan 2014 01:29:48 -0800
On Jan 15, 2014, at 12:59 AM, Quincey Morris <email@hidden> wrote:
> — When C’s reference count went to zero, object A’s reference count had also gone to zero and A’s dealloc was still pending. (This is the part I’m a bit hazy on, but the zeroing of weak references seems to be deferred sometimes, perhaps to avoid recursion in a dealloc that is invoked because a weak reference is already being zeroed.)
When an object's retain count decreases to zero, at that instant any further reads of weak variables pointing to that object (calls to objc_loadWeak()) begin to return nil. This occurs before -dealloc begins.
However, the bytes of memory storing those weak variables does not instantly become zero. The zeros usually are not written until the end of -dealloc, just before free() is called.
So if you examine the weak variable's storage via forbidden paths (such as looking at it directly in the debugger, or reading it without objc_loadWeak() in non-ARC code), then you could see a non-nil value even after the "weak reference" has become nil. But as long as you play within the rules you should not be able to observe any deferred weak reference zeroing.
> — C tried to CFRelease B, and it crashed because it couldn’t find B via its indirect reference to A.
>
> Incidentally, my fix was to make A’s reference to B __unsafe_unretained, which had the same functionality as the __weak reference but didn’t get tangled up in the zeroing. Another awful solution, but it was the best I could come up with.
It sounds more like *B's* retain count had become zero, and then something in B's -dealloc caused B to be retained and released again. Balanced retain/release during -dealloc is ordinarily perfectly safe: nothing happens. But if the releaser C was expecting to use A's weak reference to B then it would fail because the weak reference became nil just before B's -dealloc began. Changing A's reference to B into unsafe-unretained would fix that, because the unsafe-unretained pointer to B would still be accessible even after the weak pointer to B appeared to be erased.
--
Greg Parker email@hidden Runtime Wrangler
_______________________________________________
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