Re: crashes loading saved file
Re: crashes loading saved file
- Subject: Re: crashes loading saved file
- From: James Maxwell <email@hidden>
- Date: Tue, 29 May 2012 00:29:35 -0700
Hi All,
Yes, I think this general approach of trying to find a way of making reciprocal connections in initWithCoder, rather than archiving all connections, makes a great deal of sense. Quite honestly, this is an implementation of a theoretical model that is, in every conceivable way, a prototype. The priority was to figure out how to build the data structure and get it working as a musical representation. And it hasn't been easy by any stretch of the imagination. Improving and optimizing the implementation is a secondary goal and, while important, is not the focus of my research. That said, I do need to get it working for larger data sets, so I'm going to have to find some way around the current problem.
The other option of reading all the nodes as UUIDs, loading them, and making the connections later is also a good option, and quite possibly the safest. As I say, the last thing I want to do is break the structure, which has taken a long time to get right (and by "right" I mean as a music representation, not a software implementation). Since the structure is learned from musical examples, I'd rather work with it as it is, and just figure out a way of encoding/decoding it that works.
Thanks for your help, everybody.
J.
On 2012-05-28, at 11:39 PM, Quincey Morris wrote:
> 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.
>
>
James B Maxwell
Composer/Doctoral Candidate
School for the Contemporary Arts (SCA)
School for Interactive Arts + Technology (SIAT)
Simon Fraser University
_______________________________________________
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