Re: crashes loading saved file
Re: crashes loading saved file
- Subject: Re: crashes loading saved file
- From: James Maxwell <email@hidden>
- Date: Mon, 28 May 2012 20:48:12 -0700
Thanks, Quincey.
Well, I've revisited this problem many times over the past year, or so (obviously, not on a daily, or even weekly basis, but the problem has been lurking for a long time, unresolved). I've gone over the code in detail literally hundreds of times looking for the kind of problem you describe. In the parent/child relationships, the CbCMNode class has methods for "addChild" and addParent" which specifically test for identity between the node being added and self, so that a node's "childNodes" array, for example, can never contain the node itself. Nevertheless, for the sake of thoroughness, I did just place the NSAsserts you recommended in encodeWithCoder, but to no avail.
The only reason I've begun to even vaguely questioned the framework -- honestly, for the first time today -- is because I've read a number of threads today that talked about potential problems in NSKeyedUnarchiver when dealing with large, circular graphs -- one of which was actually posted by a developer from Apple (can't recall who now). Also, Mike Ash's discussions on the subject didn't help my confidence particularly...
Further, the fact that the size of the archive is a reproducible factor in the crashes seems odd. The nature of the graphs is such that size shouldn't influence the topology in any significant way (at least not considering the size and complexity of some of the graphs that do load without problems). There may be more nodes in the larger graphs, but their connectivity is fundamentally the same as with small graphs. So any obvious problem, like adding "self" to a "childNodes" array, would almost certainly show up in a smaller graph as well. Having said that, it is a complex structure, so I'll go over it again…
But in response to your general suggestion that I'm somehow immediately jumping to blaming the frameworks as a first course of action, that honestly couldn't be further from the truth.
Again, if anybody has had a similar experience, or has any further thoughts, any help would be appreciated.
J.
On 2012-05-28, at 7:58 PM, Quincey Morris wrote:
> 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.
>
>
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