What happens when I call NSMakeCollectable on a CFArrayRef?

  • I want to call a Core function that returns a CFArrayRef and make the
    result garbage collectable.
    The CFArray contains CFStrings...

    Is this pattern OK?

    -(NSArray *) doFoo {
      return NSMakeCollectable(CFCopyFoo(someArgs));
    }

    Where CFCopyFoo returns a new CFArray containing copied CFStrings.

    Or do I have to iterate over the array and call NSMakeCollectable on
    each item in it?

    AndyT (lordpixel - the cat who walks through walls)
    A little bigger on the inside

    (see you later space cowboy, you can't take the sky from me)
  • On Jan 19, 2008, at 2:56 PM, Andrew Thompson wrote:

    > I want to call a Core function that returns a CFArrayRef and make
    > the result garbage collectable.
    > The CFArray contains CFStrings...
    > Is this pattern OK?
    > -(NSArray *) doFoo {
    > return NSMakeCollectable(CFCopyFoo(someArgs));
    > }
    > Where CFCopyFoo returns a new CFArray containing copied CFStrings.
    >
    {CF,NS}MakeCollectable only apply to the argument:
    <http://developer.apple.com/documentation/Cocoa/Conceptual/GarbageCollection
    /Articles/gcCoreFoundation.html
    >

    mmalc
  • On Jan 19, 2008 2:56 PM, Andrew Thompson <lordpixel...> wrote:
    > I want to call a Core function that returns a CFArrayRef and make the
    > result garbage collectable.
    > The CFArray contains CFStrings...
    >
    > Is this pattern OK?
    >
    > -(NSArray *) doFoo {
    > return NSMakeCollectable(CFCopyFoo(someArgs));
    > }
    >
    > Where CFCopyFoo returns a new CFArray containing copied CFStrings.

    This will make the array collectable, but will do nothing to the items
    contained therein; the contents are still reference counted. However,
    this is most likely what you want anyway (Just as in pre-GC code, when
    an item is removed from the array, or the array itself is
    collected/deallocated, the item will have its reference count
    decremented, and will be deallocated if that was the last remaining
    reference).

    > Or do I have to iterate over the array and call NSMakeCollectable on
    > each item in it?

    That would do something completely different, and would not be a good
    idea (it would be akin to calling CFRelease on each of the items).

    --
    Clark S. Cox III
    <clarkcox3...>
  • On Jan 19, 2008, at 6:17 PM, Clark Cox wrote:

    > On Jan 19, 2008 2:56 PM, Andrew Thompson <lordpixel...> wrote:
    >> I want to call a Core function that returns a CFArrayRef and make the
    >> result garbage collectable.
    >> The CFArray contains CFStrings...
    >>
    >> Is this pattern OK?
    >>
    >> -(NSArray *) doFoo {
    >> return NSMakeCollectable(CFCopyFoo(someArgs));
    >> }
    >>
    >> Where CFCopyFoo returns a new CFArray containing copied CFStrings.
    >
    > This will make the array collectable, but will do nothing to the items
    > contained therein; the contents are still reference counted. However,
    > this is most likely what you want anyway (Just as in pre-GC code, when
    > an item is removed from the array, or the array itself is
    > collected/deallocated, the item will have its reference count
    > decremented, and will be deallocated if that was the last remaining
    > reference).

    That's more or less what I figured, thanks.

    >
    >> Or do I have to iterate over the array and call NSMakeCollectable on
    >> each item in it?
    >
    > That would do something completely different, and would not be a good
    > idea (it would be akin to calling CFRelease on each of the items).

    Really? I would have thought that since each is in the array, so long
    as the array isn't garbage then each string is referenced and is
    therefore also not garbage and will stick around as long as the array
    does?

    So on balance - if the strings are going to be left in the array, then
    making the array collectable is enough - once it becomes garbage the
    strings will be released too.

    Conversely if I intend to pull the strings out of the array and start
    passing them around to other objects in my program, I likely want to
    take the extra trouble to make each one collectable, otherwise I might
    forget to release them and they'll leak.

    AndyT (lordpixel - the cat who walks through walls)
    A little bigger on the inside

    (see you later space cowboy, you can't take the sky from me)
  • On Jan 20, 2008 9:42 AM, Andrew Thompson <lordpixel...> wrote:
    >
    > On Jan 19, 2008, at 6:17 PM, Clark Cox wrote:
    >
    >> On Jan 19, 2008 2:56 PM, Andrew Thompson <lordpixel...> wrote:
    >>> I want to call a Core function that returns a CFArrayRef and make the
    >>> result garbage collectable.
    >>> The CFArray contains CFStrings...
    >>>
    >>> Is this pattern OK?
    >>>
    >>> -(NSArray *) doFoo {
    >>> return NSMakeCollectable(CFCopyFoo(someArgs));
    >>> }
    >>>
    >>> Where CFCopyFoo returns a new CFArray containing copied CFStrings.
    >>
    >> This will make the array collectable, but will do nothing to the items
    >> contained therein; the contents are still reference counted. However,
    >> this is most likely what you want anyway (Just as in pre-GC code, when
    >> an item is removed from the array, or the array itself is
    >> collected/deallocated, the item will have its reference count
    >> decremented, and will be deallocated if that was the last remaining
    >> reference).
    >
    > That's more or less what I figured, thanks.
    >
    >>
    >>> Or do I have to iterate over the array and call NSMakeCollectable on
    >>> each item in it?
    >>
    >> That would do something completely different, and would not be a good
    >> idea (it would be akin to calling CFRelease on each of the items).
    >
    >
    > Really? I would have thought that since each is in the array, so long
    > as the array isn't garbage then each string is referenced and is
    > therefore also not garbage and will stick around as long as the array
    > does?

    NSMakeCollectable (and CFMakeCollectable) have to balance a retain
    (just like CFRelease has to balance a retain). Whether or not you can
    get away with doing otherwise is an implementation detail and
    shouldn't be relied upon. Additionally, you're not taking into account
    what happens to references held by code *besides* the array. For
    instance, what if one of those items happened to be held onto by some
    other code that knows nothing about GC? That other code's only way of
    ensuring that the object stays around would be to use CFRetain. But,
    if you've called NSMakeCollectable on that object, you've just removed
    that code's reference without its knowing.

    > So on balance - if the strings are going to be left in the array, then
    > making the array collectable is enough - once it becomes garbage the
    > strings will be released too.

    Yes

    > Conversely if I intend to pull the strings out of the array and start
    > passing them around to other objects in my program, I likely want to
    > take the extra trouble to make each one collectable, otherwise I might
    > forget to release them and they'll leak.

    Yes.

    Just remember to stick to the memory management contracts and you'll be fine:
    <http://developer.apple.com/documentation/CoreFoundation/Conceptual/CFMemory
    Mgmt/Concepts/Ownership.html
    >

    --
    Clark S. Cox III
    <clarkcox3...>
previous month january 2008 next month
MTWTFSS
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
Go to today