NSUnarchiver - Why does this leak?

  • Recently leaks was showing some massive leakage in my code, and I've
    narrowed it down to some unarchiving of a dictionary, and the data stored in
    that dictionary. The dictionary is stored in a file, and the objects in the
    dictionary are archived NSData objects that were archived from a simple
    model object with a few NSStrings and an NSCalendarDate.

    The reduced code that causes the leaks looks like:

    - (void)leakTest
    {
        NSData                *archivedData;
        NSMutableDictionary *archivedDictionary;
        NSMutableArray        *archivedArray;

        archivedDictionary = [NSUnarchiver
                unarchiveObjectWithFile:path];
        archivedData = [archivedDictionary objectForKey:@"Some_Key"];
        archivedArray = [NSUnarchiver unarchiveObjectWithData:indexingData];
        //this does not mitigate the leaking:
        //[archivedArray removeAllObjects];
    }

    After exiting leakTest, the instance variables of every object in the
    archivedArray are leaked, or so leaks tells me. Those objects have a simple
    initWithCoder method:

    - (id)initWithCoder:(NSCoder *)coder
    {
        [self setName:[coder decodeObject]];
        [self setPath:[coder decodeObject]];
        [self setModDate:[coder decodeObject]];

        return self;
    }

    It's as if while archivedArray is autoreleased, the leaf-level objects
    inside of it unarchived by NSUnarchiver are not. What's the correct way to
    handle this?

    Thanks
    John
    _______________________________________________
    cocoa-dev mailing list | <cocoa-dev...>
    Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    Do not post admin requests to the list. They will be ignored.
  • If I recall correctly, the decoded objects are owned by NSUnarchiver.
    Once the unarchiver object is destroyed, all the objects it decoded
    will also be released.  The unarchiver below is autoreleased, so
    testing for leaks immediately after invoking leakTest will produce
    misleading results.  Try using an autorelease pool in leakTest and
    check for leaks after releasing the pool.  I suspect that it won't
    appear to be leaking anymore.

    On Sunday, March 30, 2003, at 08:24  PM, John Scalo wrote:

    > Recently leaks was showing some massive leakage in my code, and I've
    > narrowed it down to some unarchiving of a dictionary, and the data
    > stored in
    > that dictionary. The dictionary is stored in a file, and the objects
    > in the
    > dictionary are archived NSData objects that were archived from a simple
    > model object with a few NSStrings and an NSCalendarDate.
    >
    > The reduced code that causes the leaks looks like:
    >
    > - (void)leakTest
    > {
    > NSData                *archivedData;
    > NSMutableDictionary *archivedDictionary;
    > NSMutableArray        *archivedArray;
    >
    > archivedDictionary = [NSUnarchiver
    > unarchiveObjectWithFile:path];
    > archivedData = [archivedDictionary objectForKey:@"Some_Key"];
    > archivedArray = [NSUnarchiver
    > unarchiveObjectWithData:indexingData];
    > //this does not mitigate the leaking:
    > //[archivedArray removeAllObjects];
    > }
    >
    > After exiting leakTest, the instance variables of every object in the
    > archivedArray are leaked, or so leaks tells me. Those objects have a
    > simple
    > initWithCoder method:
    >
    > - (id)initWithCoder:(NSCoder *)coder
    > {
    > [self setName:[coder decodeObject]];
    > [self setPath:[coder decodeObject]];
    > [self setModDate:[coder decodeObject]];
    >
    > return self;
    > }
    >
    > It's as if while archivedArray is autoreleased, the leaf-level objects
    > inside of it unarchived by NSUnarchiver are not. What's the correct
    > way to
    > handle this?
    >
    > Thanks
    > John
    > _______________________________________________
    > cocoa-dev mailing list | <cocoa-dev...>
    > Help/Unsubscribe/Archives:
    > http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    > Do not post admin requests to the list. They will be ignored.
    >
    >
    Daryn
    _______________________________________________
    cocoa-dev mailing list | <cocoa-dev...>
    Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    Do not post admin requests to the list. They will be ignored.
  • Thanks Daryn. I don't think that explains it, though. For one, I'm not
    running leaks until well after the app has returned to its event loop, so
    everything marked for autoreleasing should be. Also, adding an autorelease
    pool to the test routine didn't change the outcome of leaks.

    Leaks has been fairly reliable for me in the past, but could it be wrong
    here?

    On 3/30/03 9:05 PM, "Daryn" <cryx...> wrote:

    > If I recall correctly, the decoded objects are owned by NSUnarchiver.
    > Once the unarchiver object is destroyed, all the objects it decoded
    > will also be released.  The unarchiver below is autoreleased, so
    > testing for leaks immediately after invoking leakTest will produce
    > misleading results.  Try using an autorelease pool in leakTest and
    > check for leaks after releasing the pool.  I suspect that it won't
    > appear to be leaking anymore.
    >
    > On Sunday, March 30, 2003, at 08:24  PM, John Scalo wrote:
    >
    >> Recently leaks was showing some massive leakage in my code, and I've
    >> narrowed it down to some unarchiving of a dictionary, and the data
    >> stored in
    >> that dictionary. The dictionary is stored in a file, and the objects
    >> in the
    >> dictionary are archived NSData objects that were archived from a simple
    >> model object with a few NSStrings and an NSCalendarDate.
    >>
    >> The reduced code that causes the leaks looks like:
    >>
    >> - (void)leakTest
    >> {
    >> NSData                *archivedData;
    >> NSMutableDictionary *archivedDictionary;
    >> NSMutableArray        *archivedArray;
    >>
    >> archivedDictionary = [NSUnarchiver
    >> unarchiveObjectWithFile:path];
    >> archivedData = [archivedDictionary objectForKey:@"Some_Key"];
    >> archivedArray = [NSUnarchiver
    >> unarchiveObjectWithData:indexingData];
    >> //this does not mitigate the leaking:
    >> //[archivedArray removeAllObjects];
    >> }
    >>
    >> After exiting leakTest, the instance variables of every object in the
    >> archivedArray are leaked, or so leaks tells me. Those objects have a
    >> simple
    >> initWithCoder method:
    >>
    >> - (id)initWithCoder:(NSCoder *)coder
    >> {
    >> [self setName:[coder decodeObject]];
    >> [self setPath:[coder decodeObject]];
    >> [self setModDate:[coder decodeObject]];
    >>
    >> return self;
    >> }
    >>
    >> It's as if while archivedArray is autoreleased, the leaf-level objects
    >> inside of it unarchived by NSUnarchiver are not. What's the correct
    >> way to
    >> handle this?
    >>
    >> Thanks
    >> John
    >> _______________________________________________
    >> cocoa-dev mailing list | <cocoa-dev...>
    >> Help/Unsubscribe/Archives:
    >> http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    >> Do not post admin requests to the list. They will be ignored.
    >>
    >>
    > Daryn
    _______________________________________________
    cocoa-dev mailing list | <cocoa-dev...>
    Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    Do not post admin requests to the list. They will be ignored.
  • I'm not an archiving expert by any means, however I suspect that Leaks
    is telling the truth and that memory management is being mishandled
    somewhere.  If feasible, you may try overriding retain/release and set
    a breakpoint on them or generate NSLog output in order to find what
    object is still retaining.

    On Monday, March 31, 2003, at 12:14  AM, John Scalo wrote:

    > Thanks Daryn. I don't think that explains it, though. For one, I'm not
    > running leaks until well after the app has returned to its event loop,
    > so
    > everything marked for autoreleasing should be. Also, adding an
    > autorelease
    > pool to the test routine didn't change the outcome of leaks.
    >
    > Leaks has been fairly reliable for me in the past, but could it be
    > wrong
    > here?
    >
    > On 3/30/03 9:05 PM, "Daryn" <cryx...> wrote:
    >
    >> If I recall correctly, the decoded objects are owned by NSUnarchiver.
    >> Once the unarchiver object is destroyed, all the objects it decoded
    >> will also be released.  The unarchiver below is autoreleased, so
    >> testing for leaks immediately after invoking leakTest will produce
    >> misleading results.  Try using an autorelease pool in leakTest and
    >> check for leaks after releasing the pool.  I suspect that it won't
    >> appear to be leaking anymore.
    >>
    >> On Sunday, March 30, 2003, at 08:24  PM, John Scalo wrote:
    >>
    >>> Recently leaks was showing some massive leakage in my code, and I've
    >>> narrowed it down to some unarchiving of a dictionary, and the data
    >>> stored in
    >>> that dictionary. The dictionary is stored in a file, and the objects
    >>> in the
    >>> dictionary are archived NSData objects that were archived from a
    >>> simple
    >>> model object with a few NSStrings and an NSCalendarDate.
    >>>
    >>> The reduced code that causes the leaks looks like:
    >>>
    >>> - (void)leakTest
    >>> {
    >>> NSData                *archivedData;
    >>> NSMutableDictionary *archivedDictionary;
    >>> NSMutableArray        *archivedArray;
    >>>
    >>> archivedDictionary = [NSUnarchiver
    >>> unarchiveObjectWithFile:path];
    >>> archivedData = [archivedDictionary objectForKey:@"Some_Key"];
    >>> archivedArray = [NSUnarchiver
    >>> unarchiveObjectWithData:indexingData];
    >>> //this does not mitigate the leaking:
    >>> //[archivedArray removeAllObjects];
    >>> }
    >>>
    >>> After exiting leakTest, the instance variables of every object in the
    >>> archivedArray are leaked, or so leaks tells me. Those objects have a
    >>> simple
    >>> initWithCoder method:
    >>>
    >>> - (id)initWithCoder:(NSCoder *)coder
    >>> {
    >>> [self setName:[coder decodeObject]];
    >>> [self setPath:[coder decodeObject]];
    >>> [self setModDate:[coder decodeObject]];
    >>>
    >>> return self;
    >>> }
    >>>
    >>> It's as if while archivedArray is autoreleased, the leaf-level
    >>> objects
    >>> inside of it unarchived by NSUnarchiver are not. What's the correct
    >>> way to
    >>> handle this?
    >>>
    >>> Thanks
    >>> John
    >>> _______________________________________________
    >>> cocoa-dev mailing list | <cocoa-dev...>
    >>> Help/Unsubscribe/Archives:
    >>> http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    >>> Do not post admin requests to the list. They will be ignored.
    >>>
    >>>
    >> Daryn
    >>
    >
    >
    Daryn
    _______________________________________________
    cocoa-dev mailing list | <cocoa-dev...>
    Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    Do not post admin requests to the list. They will be ignored.
  • Outcome: The dealloc method in one of my classes wasn't releasing a few
    instance variables, but this only manifested itself when lots of objects
    were instantiated sequentially into the NSMutableArray that was being
    archived and subsequently unarchived. So, the leaks didn't show up until
    much later when I unarchived the array.

    It's always the simple stuff, but the simple stuff is the hardest to track
    down...

    On 3/31/03 10:41 PM, "Daryn" <cryx...> wrote:

    > I'm not an archiving expert by any means, however I suspect that Leaks
    > is telling the truth and that memory management is being mishandled
    > somewhere.  If feasible, you may try overriding retain/release and set
    > a breakpoint on them or generate NSLog output in order to find what
    > object is still retaining.
    >
    > On Monday, March 31, 2003, at 12:14  AM, John Scalo wrote:
    >
    >> Thanks Daryn. I don't think that explains it, though. For one, I'm not
    >> running leaks until well after the app has returned to its event loop,
    >> so
    >> everything marked for autoreleasing should be. Also, adding an
    >> autorelease
    >> pool to the test routine didn't change the outcome of leaks.
    >>
    >> Leaks has been fairly reliable for me in the past, but could it be
    >> wrong
    >> here?
    >>
    >> On 3/30/03 9:05 PM, "Daryn" <cryx...> wrote:
    >>
    >>> If I recall correctly, the decoded objects are owned by NSUnarchiver.
    >>> Once the unarchiver object is destroyed, all the objects it decoded
    >>> will also be released.  The unarchiver below is autoreleased, so
    >>> testing for leaks immediately after invoking leakTest will produce
    >>> misleading results.  Try using an autorelease pool in leakTest and
    >>> check for leaks after releasing the pool.  I suspect that it won't
    >>> appear to be leaking anymore.
    >>>
    >>> On Sunday, March 30, 2003, at 08:24  PM, John Scalo wrote:
    >>>
    >>>> Recently leaks was showing some massive leakage in my code, and I've
    >>>> narrowed it down to some unarchiving of a dictionary, and the data
    >>>> stored in
    >>>> that dictionary. The dictionary is stored in a file, and the objects
    >>>> in the
    >>>> dictionary are archived NSData objects that were archived from a
    >>>> simple
    >>>> model object with a few NSStrings and an NSCalendarDate.
    >>>>
    >>>> The reduced code that causes the leaks looks like:
    >>>>
    >>>> - (void)leakTest
    >>>> {
    >>>> NSData                *archivedData;
    >>>> NSMutableDictionary *archivedDictionary;
    >>>> NSMutableArray        *archivedArray;
    >>>>
    >>>> archivedDictionary = [NSUnarchiver
    >>>> unarchiveObjectWithFile:path];
    >>>> archivedData = [archivedDictionary objectForKey:@"Some_Key"];
    >>>> archivedArray = [NSUnarchiver
    >>>> unarchiveObjectWithData:indexingData];
    >>>> //this does not mitigate the leaking:
    >>>> //[archivedArray removeAllObjects];
    >>>> }
    >>>>
    >>>> After exiting leakTest, the instance variables of every object in the
    >>>> archivedArray are leaked, or so leaks tells me. Those objects have a
    >>>> simple
    >>>> initWithCoder method:
    >>>>
    >>>> - (id)initWithCoder:(NSCoder *)coder
    >>>> {
    >>>> [self setName:[coder decodeObject]];
    >>>> [self setPath:[coder decodeObject]];
    >>>> [self setModDate:[coder decodeObject]];
    >>>>
    >>>> return self;
    >>>> }
    >>>>
    >>>> It's as if while archivedArray is autoreleased, the leaf-level
    >>>> objects
    >>>> inside of it unarchived by NSUnarchiver are not. What's the correct
    >>>> way to
    >>>> handle this?
    >>>>
    >>>> Thanks
    >>>> John
    >>>> _______________________________________________
    >>>> cocoa-dev mailing list | <cocoa-dev...>
    >>>> Help/Unsubscribe/Archives:
    >>>> http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    >>>> Do not post admin requests to the list. They will be ignored.
    >>>>
    >>>>
    >>> Daryn
    >>>
    >>
    >>
    > Daryn
    _______________________________________________
    cocoa-dev mailing list | <cocoa-dev...>
    Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    Do not post admin requests to the list. They will be ignored.
previous month march 2003 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