More GC. Now with NSData

  • Thanks Joar for answering my last one.

    I'm doing some fairy low level data interpretation, and using NSData
    to make my life a bit easier.

    I have an NSData that contains the complete set of data called
    fullDataDump. I walk through this, partitioning it up into sub-blocks
    with code something like this:

        fullData = [fullDataDump bytes];

        while (currentAddress < finalAddress) {
            length = fullData[0];
    NSData newRecord = [NSData dataWithBytesNoCopy:(void *) (fullData +
    currentAddress) length:length freeWhenDone:NO]];
            [rawDives addObject:newRecord];
        }

    i.e. creating an array of NSDatas that point into the same memory
    space as the original.

    My question is this, I've created these NSDatas without copying the
    bytes, so have I put myself in a position where the garbage collector
    could release the memory beneath them if the original fullDataDump
    NSData was released?

    I'm thinking this might happen because the new NSDatas will have
    pointers into the middle of the original memory allocation, rather
    than the beginning.
  • On 26 Nov 2007, at 17:20, Paul Sargent wrote:

    > I have an NSData that contains the complete set of data called
    > fullDataDump. I walk through this, partitioning it up into sub-
    > blocks with code something like this:
    >
    > fullData = [fullDataDump bytes];
    >
    > while (currentAddress < finalAddress) {
    > length = fullData[0];
    > NSData newRecord = [NSData dataWithBytesNoCopy:(void *) (fullData +
    > currentAddress) length:length freeWhenDone:NO]];
    > [rawDives addObject:newRecord];
    > }
    >
    > i.e. creating an array of NSDatas that point into the same memory
    > space as the original.
    >
    > My question is this, I've created these NSDatas without copying the
    > bytes, so have I put myself in a position where the garbage
    > collector could release the memory beneath them if the original
    > fullDataDump NSData was released?

    Yes.  The garbage collector doesn't support interior pointers.  You
    need to keep the original object around by holding on to a reference
    to it until you're done with all of your data objects.

    A better approach to the problem would be to use NSData's -
    subdataWithRange: method; that will avoid having to do pointer
    arithmetic and will also avoid entirely the problem with the garbage
    collector.

    Kind regards,

    Alastair.

    --
    http://alastairs-place.net
  • On Nov 26, 2007, at 12:44 PM, Alastair Houghton wrote:

    > On 26 Nov 2007, at 17:20, Paul Sargent wrote:
    >
    >> I have an NSData that contains the complete set of data called
    >> fullDataDump. I walk through this, partitioning it up into sub-
    >> blocks with code something like this:
    >>
    >> fullData = [fullDataDump bytes];
    >>
    >> while (currentAddress < finalAddress) {
    >> length = fullData[0];
    >> NSData newRecord = [NSData dataWithBytesNoCopy:(void *) (fullData
    >> + currentAddress) length:length freeWhenDone:NO]];
    >> [rawDives addObject:newRecord];
    >> }
    >>
    >> i.e. creating an array of NSDatas that point into the same memory
    >> space as the original.
    >>
    >> My question is this, I've created these NSDatas without copying
    >> the bytes, so have I put myself in a position where the garbage
    >> collector could release the memory beneath them if the original
    >> fullDataDump NSData was released?
    >
    > Yes.  The garbage collector doesn't support interior pointers.  You
    > need to keep the original object around by holding on to a
    > reference to it until you're done with all of your data objects.

    Doesn't -dataWithBytesNoCopy:length:freeWhenDone: do the Right Thing
    (tm) with respect to marking the returned NSData instance as non-
    collectible when the third param is NO?

    IMHO, it should, and if it doesn't, that sounds like a bug.

    > A better approach to the problem would be to use NSData's -
    > subdataWithRange: method; that will avoid having to do pointer
    > arithmetic and will also avoid entirely the problem with the
    > garbage collector.

    Good point. Consider the above a question of curiosity. :-)

    sherm--

    Web Hosting by West Virginians, for West Virginians: http://wv-www.net
    Cocoa programming in Perl: http://camelbones.sourceforge.net
  • On 26 Nov 2007, at 17:56, Sherm Pendley wrote:

    > Doesn't -dataWithBytesNoCopy:length:freeWhenDone: do the Right Thing
    > (tm) with respect to marking the returned NSData instance as non-
    > collectible when the third param is NO?
    >
    > IMHO, it should, and if it doesn't, that sounds like a bug.

    No, because the NSData instance is still perfectly collectable.  The
    underlying data isn't, but that's not the problem here.  The problem
    is that the underlying NSData (the one that actually holds the memory)
    can be garbage collected if the last reference to it disappears, which
    can easily happen in code like this because the GC ignores interior
    pointers.  i.e. the pointers that the new NSDatas keep to their data
    aren't enough to keep the original NSData alive because they don't
    point to the original NSData object itself.

    Kind regards,

    Alastair.

    --
    http://alastairs-place.net
  • On 26 Nov 2007, at 17:44, Alastair Houghton wrote:

    > On 26 Nov 2007, at 17:20, Paul Sargent wrote:
    >
    >> My question is this, I've created these NSDatas without copying the
    >> bytes, so have I put myself in a position where the garbage
    >> collector could release the memory beneath them if the original
    >> fullDataDump NSData was released?
    >
    > Yes.  The garbage collector doesn't support interior pointers.  You
    > need to keep the original object around by holding on to a reference
    > to it until you're done with all of your data objects.
    >
    > A better approach to the problem would be to use NSData's -
    > subdataWithRange: method; that will avoid having to do pointer
    > arithmetic and will also avoid entirely the problem with the garbage
    > collector.

    Ahh, Thanks. Still not 100% familiar with all the functionality
    available.

    Just to be clear, -subdataWithRange will make a copy of the data into
    it's own buffer, which the new NSData will own. Hence it'll be safe.
    Right?
  • On 26 Nov 2007, at 20:38, Paul Sargent <psarge...> wrote:

    > Just to be clear, -subdataWithRange will make a copy of the data
    > into it's own buffer, which the new NSData will own. Hence it'll be
    > safe. Right?

    It might not make an actual copy if you're using an immutable NSData,
    but that's an implementation detail. The important thing is that it
    will be safe.

    Kind regards,

    Alastair

    --
    http://alastairs-place.net
previous month november 2007 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    
Go to today