Bizarre NSSet copying crash

I have a class that contains an NSSet . That object is called _collectibles , and in a method, I make a copy of that set in order to do some processing, something like:

NSSet* collectibleCopy = [_collectibles copy];

In practice, I see this regularly crash with this message:

[__NSPlaceholderSet initWithObjects:count:]: attempt to insert nil object from objects

I've resolved the issue by changing the above code to:

NSMutableSet* collectibleCopy = [[NSMutableSet alloc] initWithCapacity: [_collectibles count]];
for ( id thing in _collectibles ) {
    [collectibleCopy addObject: thing];
}

And now I can no longer reproduce any such crash. I'm betting [copy] is more efficient, and I'd rather use it, but I can't figure out why it's completely wonky!

Update: while full context would take a ton of explanation, the keys to me solving this were that, a, the code was invoked this way:

NSBlockOperation* operation = [NSBlockOperation blockOperationWithBlock: ^{
   [thing doStuff];
}];

[operationQueue addOperation: operation];

And that I was, basically by making a bunch of things slower, catch the app with 2 threads running 2 threads for a queue initialized thusly:

operationQueue.maxConcurrentOperationCount = 1;

Which I thought impossible. The clue was that the second thread was in [NSAutoreleasePool drain], which led me to learn that NSOperationQueue can do autorelease stuff whenever/however it wants.


Would

NSSet* collectibleCopy = [NSSet setWithSet:_collectibles] 

work for you?


OK, so huzzah for having actually figured this out.

The trick here was that this operation was performed on an async NSOperationQueue . TIL that NSOperationQueues have AutoreleasePools, but that they get drained at the discretion of GCD. In this case, the pool from a previous operation was being drained on another thread concurrently, causing what amounts to a rather opaque concurrent modification problem.

Solution:

@autoreleasepool inside the block on which this code got invoked. This causes the drain to happen as part of the block, rather than asynchronously, and my race condition goes away.

链接地址: http://www.djcxy.com/p/71594.html

上一篇: xmlhttpRequest未定义

下一篇: 奇怪的NSSet复制崩溃