• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Encoding infinite loops
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Encoding infinite loops


  • Subject: Re: Encoding infinite loops
  • From: Chris Kane <email@hidden>
  • Date: Mon, 21 May 2007 09:47:00 -0700

This (very probably -- I haven't looked into it) is not a problem with the recursion per-se, but rather with objects which replace themselves during unarchiving by returning a new object from initWithCoder:.

Consider for a moment an object unarchiving itself. The unarchiver has created the object for that reference in the archive and is initializing it. The object unarchives a bunch of other state, some of which is more objects. If one of the subobjects has a reference to the original object, and unarchives that, the unarchiver happily gives it the object which it has already created for that object -- but in this case note that that object is still initializing itself. This can create two sorts of problems, but in the lucky case everything unwinds and things work out and the recursive reference has been restored by the unarchiver.

The two problems are obvious with a little thought: (1) the subobject now has a pointer to an object which is not fully initialized (because it is in the middle of being initialized higher on the stack), and so if the subobject actually tries to *do* anything with the object other than unarchive it, trouble will likely unsue; and (2) if the original object replaces itself by returning a new object from initWithCoder: -- which is defined as OK and actually required to accomplish some designs, like singletons -- then every object which got the OLD pointer probably now has a pointer to a freed object, or something equally useless.

Both NSUnarchiver and NSKeyedUnarchiver have this same pitfall. I pushed some to get these fixed when NSKeyedUnarchiver was being designed, but it basically requires every NSCoding object to participate by implementing a new method to react to the replacement, and other new checks during unarchiving. It's not just the unarchiver or the classes which might replace the original object which have to do more work, its every class which might get an object which might replace itself during unarchiving which has to participate, because those are the objects that have done something with that pointer and only they know where that pointer got stored, if anywhere, and what else might have been done with it.

This was considered too much effort for an archane situation to be worth trying to fix, since the fix wasn't just some extra effort localized to the unarchiver. We knew of a couple reports of developers who'd hit this in all the previous years with NSUnarchiver and the rate has not increased in the years since NSKeyedUnarchiver was introduced either.


So the summary answer is: you can't reliably have recursive references. In practice, though, these do occur (think of the NSView subview/superview relationship) and things squeak by. Sometimes they don't and it's impossible to know beforehand if something will work or not.



Chris Kane Cocoa Frameworks, Apple


On May 21, 2007, at 7:15 AM, Will Thimbleby wrote:

I'm having trouble encoding this array containing an infinite loop:

NSMutableArray *a = [[NSMutableArray alloc] init];
[a addObject:a];

Yes I'm using NSKeyedArchiver and I've tried various ways of encoding the array, but when decoded none of the arrays are correct. Here's my current test code:

		NSMutableArray *a = [[NSMutableArray alloc] init];
		[a addObject:a];

		NSLog(@"%d, %d", a, [a lastObject]);

NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *ka = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[ka encodeObject:a];
[ka finishEncoding];


NSKeyedUnarchiver *ku = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
a = [ku decodeObject];
[ku finishDecoding];


		NSLog(@"%d, %d", a, [a lastObject]);

The last object of the array "a" is uninitalised and useless. Any ideas welcome.

cheers
--Will
_______________________________________________

Cocoa-dev mailing list (email@hidden)

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

_______________________________________________

Cocoa-dev mailing list (email@hidden)

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


  • Follow-Ups:
    • Re: Encoding infinite loops
      • From: Uli Kusterer <email@hidden>
References: 
 >Encoding infinite loops (From: Will Thimbleby <email@hidden>)

  • Prev by Date: Re: notifications
  • Next by Date: Re: Dock icon removal. and NSStatusBar
  • Previous by thread: Re: Encoding infinite loops
  • Next by thread: Re: Encoding infinite loops
  • Index(es):
    • Date
    • Thread