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