Re: CoreFoundation object over-retained during finalization
Re: CoreFoundation object over-retained during finalization
- Subject: Re: CoreFoundation object over-retained during finalization
- From: Quincey Morris <email@hidden>
- Date: Fri, 11 Mar 2011 10:42:06 -0800
On Mar 11, 2011, at 08:21, email@hidden wrote:
> I interpret this to mean:
>
> During the freeing of memory marked as collectable a SecKeychain object was found with a ref count of 1.
>
> I cannot quite convince myself how this arises for a CF object in a GC envionment.
> From reading the memory manage docs my best estimate of how this occurs is.
>
> I allocate an opaque object of type SecKeychain pointed to by a SecKeychainRef.
> CFRelease(SecKeychainRef) gets called somewhere. Retain count goes to 0. The object will now be collected when no longer rooted.
> The object receives a further retain but no matching CFRelease().
> The object becomes no longer referenced by another object, or the stack etc.
> The object is collected and the positive retain count is encountered.
>
> Is the above strictly correct or am I missing something?
You're missing something -- see below.
> The most pertinent bit of
> http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/GarbageCollection/Articles/gcCoreFoundation.html#//apple_ref/doc/uid/TP40006687-SW1
> seems to be:
>
> The difference between the garbage-collected environment and reference-counted environment is in the timing of the object’s deallocation. In a reference counted environment, when the object’s retain count drops to 0 it is deallocated immediately; in a garbage-collected environment, what happens when a Core Foundation object's retain count transitions from 1 to 0 depends on where it resides in memory:
> If the object is in the malloc zone, it is deallocated immediately.
> If the object is in the garbage collected zone, the last CFRelease() does not immediately free the object, it simply makes it eligible to be reclaimed by the collector when it is discovered to be unreachable—that is, once all strong references to it are gone. Thus as long as the object is still referenced from an object-type instance variable (that hasn't been marked as__weak), a register, the stack, or a global variable, it will not be collected.
This description** is slightly different from yours. According to this, the following is false:
> CFRelease(SecKeychainRef) gets called somewhere. Retain count goes to 0. The object will now be collected when no longer rooted.
because you don't know whether the object will be deallocated immediately or not. The Apple documentation says that it depends on what zone the object's in. That means it isn't safe to CFRelease something (that you own) and then CFRetain it again -- it may already be gone. However, let's assume it's in the collector zone, so doesn't disappear immediately. Your bug is something different.
Whether the CF object got a CFRelease/CFRetain pair sometime before the crash or not, your problem is that it needs:
-- *either* to be CFRelease'd when its owner is done with it during the normal course of business
-- *or* to be CFRRelease'd in the 'finalize' of the object that owns it
-- *or* to be CFMakeAllocatable'd after it was created**
You owned it when you created it, but you apparently never balanced that with a CFRelease/CFMakeAllocatable. If you wrote any other code that CFRetain'ed it, of course, that code also needs to arrange for its own balancing CFRelease.
** Note that the CFRelease inside CFMakeAllocatable is safe, because CFMakeAllocatable checks that the object is in the collector zone, and keeps a temporary strong reference that prevents it from being collected before it gets handed back to you.
_______________________________________________
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