On May 28, 2012, at 15:14 , James Maxwell wrote:

> Just to recap the problem: I get a exc_bad_access crash when unarchiving 
> certain files from disk. The file is a keyed archive, which contains a fairly 
> complex custom object graph, with plenty of circular references (i.e., 
> parentNode <---> childNode stuff). When this graph is relatively small I have 
> no problems. But when it gets larger, it crashes. As mentioned previously, 
> one seemingly significant thing about the crash is that the backtrace is 
> >25,000 frames long. I've taken this to suggest that perhaps: A) some 
> circular reference is getting stuck in a loop, or B) the graph is large 
> enough that, while the unarchiver is trying to keep track of circular 
> references, the stack overflows. I don't know if either of these 
> possibilities makes sense, so I'm wondering how I might test for each?
> 
> Partly because the massive backtrace isn't just a list of identical calls, 
> and partly because the unarchiver is supposed to handle circular references, 
> I kind of suspect B. But, if this is the case, how can I get around it? I 
> already use archiveRootObject:toFile for archiving, so I would think I should 
> be exploiting the built-in recursion checking stuff… Accordingly, I use 
> unarchiveObjectWithFile to unarchive the graph. Everything I've done is 
> pretty basic stuff, so perhaps my structure calls for a more advanced 
> approach(??) I did include @autoreleasepool blocks in a couple of places, 
> where  temporary objects could be created during initialization. But that 
> didn't help… 

I think you're approaching this incorrectly.

At best, you're stating the problem neutrally ("is getting stuck in a loop") as 
if uncertain whether to blame the frameworks (NSKeyedUnarchiver specifically) 
or your own code. This is a mistake. You *must* assume that you're doing 
something wrong, *until and unless* you find specific evidence that the 
frameworks are at fault.

It's not that there can't be bugs in Cocoa frameworks. There are plenty. 
Rather, the rationale is that classes like NSKeyedUnarchiver have been used 
innumerable times, while your code has been used successfully -- how many times?

Next, it's not remotely credible that NSKeyedUnarchiver is designed to recurse 
in a way that could put 25,000 frame on the stack. This would mean, for 
example, that NSKeyedUnarchiver wasn't usable in background threads, which by 
default have a *very* small stack.

Occam's Razor says that you have a bug in your code.

My guess is, given the backtrace you originally posted, that you've somehow 
added an object to one of its own array instance variables. That could well put 
NSKeyedUnarchiver into an infinite tailspin. (This would not be "parentNode 
<---> childNode stuff". It would be claiming that an object is its own child, 
which is a relationship you can't expect unarchiving to deal with, if you think 
about the order in which things happen.) The backtrace even appears to tell you 
the class of the object that's doing this: CbCMNode. According to the 
backtrace, this object is unarchiving an array object key, and that unarchives 
an instance of CbCMNode, which unarchives … . 

You might have an easier time of detecting this during archiving, rather than 
unarchiving. How about you add something like this to [CbCMNode 
encodeWithCoder:]:

        NSAssert (![self->whateverArray containsObjectIdenticalTo: self], @"Er, 
this shouldn't happen");

Depending on the bug in your code, it might be a bit harder to find out where 
it's going wrong. However, as long as there's a small voice in your mind trying 
to throw the blame on the frameworks, you won't get anywhere.


_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to