Re: crashes loading saved file
Re: crashes loading saved file
- Subject: Re: crashes loading saved file
- From: Quincey Morris <email@hidden>
- Date: Mon, 28 May 2012 23:39:10 -0700
On May 28, 2012, at 22:08 , James Maxwell wrote:
> Well, yes, that's what happens. In fact, it's much hairier than that! There's actually an array of parentNodes, not just one. It's a complex graph, as I mentioned, not a straightforward tree (which would already contain mutual parent/child references, it seems to me). In my structure, there are about three dimensions of this kind of referencing, allowing me to move around the graph in useful ways… It's encoding hierarchical musical structure, for a music learning/generation algorithm, so there's a lot of complexity involved. As I say, it loads fine with smaller files, and testing the structure after loading indicates that it has been reconstructed properly. This is why I suspect there's a problem with trying to keep track of all these relationships during unarchiving, which NSKeyedUnarchiver does on the stack, afaik. There's an interesting discussion on this here:
I think have been stupid and still am stupid.
(Still stupid because I don't understand how unarchiving can *validly* resolve mutual references without returning an incompletely-initialized -- in the sense of not yet having "returned self" -- object to at least one of the referrers. But perhaps there's an inherent/implied/undocumented restriction on the kinds of shenanigans that 'initWithCoder:' is allowed to get up to.)
That aside, I have a suspicion, or perhaps it's just wild speculation, that NSKeyedUnarchiver has some built-in safeguards that mean it can't just (in effect) walk your object graph visiting each node once, but needs (in effect) to walk every path through the graph, so that it actually visits nodes more than once. And it does this through recursion. For a strictly hierarchical object graph, there's no difference between the two strategies, but certain other kinds of object graphs will take a lot of stack space and (even if it doesn't overflow the stack) will perform very badly.
Whatever the explanation, I think the solution is still not to archive both parent and child pointers. Instead of this:
> [aCoder encodeObject:parentNodes forKey:@"parentNodes"];
> [aCoder encodeObject:childNodes forKey:@"childNodes"];
just this:
> [aCoder encodeObject:childNodes forKey:@"childNodes"];
and instead of this:
> parentNodes = [[aDecoder decodeObjectForKey:@"parentNodes"] retain];
> childNodes = [[aDecoder decodeObjectForKey:@"childNodes"] retain];
something like this:
> parentNodes = [[NSMutableArray alloc] init];
> childNodes = [[aDecoder decodeObjectForKey:@"childNodes"] retain];
> for (CbCMNode* node in childNodes)
> [node->parentNodes addObject: node];
If that's not satisfactory, then I think what you need to do is something like what I imagine Core Data does. Instead of archiving object pointers (at least for the potentially mutual references such as parents and children), assign and archive UUIDs, and archive a global dictionary whose keys are the UUIDs and whose objects are the CbCMNode instances. After you've finished unarchiving the object graph, walk it one more time yourself, replacing parent/child UUIDs with the corresponding objects as you go.
Regardless of whether your crash is a bug, a design defect, a limitation, or whatever, one of these approaches should relieve NSKeyedUnarchiver of the need to deal with complicated object graphs.
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please 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