Re: Encoding infinite loops
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