exc_bad_access для insertNewObjectForEntityForName:inManagedObjectContext
Я написал минимальный пример кода проблемы, которую я имею. Я реализовал фоновую работу двумя способами: вручную порождая потоки и позволяя NSOperation
обрабатывать резьбу. В обоих случаях я создаю NSManagedObjectContexts
для каждого потока / операции.
Когда я сам создаю темы performSelectorInBackground:withObject:
все отлично работает Когда я переключаюсь на передачу своих объектов NSOperationQueue
Я вижу следующие ошибки при попытке сохранить операции NSManagedObjectContext
,
-EXC_BAD_ACCESS - серьезная ошибка приложения. Исключительная ситуация при обработке изменения базовых данных: *** -[NSCFSet addObject:]: попытка вставить nil с userInfo (null) - _referenceData64, определенная только для абстрактного класса. Определить -[NSTevenObjectID_default _referenceData64]!
Я считаю, что ошибка, особенно с учетом последней ошибки, связана с использованием временного objectID для передачи объектов между потоками / контекстами. Возможно, еще хуже, я как-то прохожу NSManagedObjects
между нитями.
В любом случае, я не могу найти код, который бы подсказывал, что я делаю это.
Мой минимальный пример кода можно найти здесь.
Большая часть работы выполняется в AppDelegate
в awakeFromNib
, Задавать EXECUTE_WITH_NSOPERATION
до 0, чтобы бежать с performSelectorInBackground:withObject:
, Покидать EXECUTE_WITH_NSOPERATION
на 1 выполнить с NSOperationQueue
который создает кучу MCBoardParse
объекты.
Я вижу это только под 10.6.
оригинал
У меня есть приложение Какао, построенное на 10,5 фреймворках. В NSOperation
В цикле я быстро создаю сотни NSManagedObjects
, Часто создание тех NSManagedObejcts
произойдет сбой с ошибкой EXC_BAD_ACCESS. Это происходит как при управлении ссылочной памятью, так и при сборке мусора.
for (offsetCount; offsetCount < [parsedData count]; offsetCount++) {
NSManagedObject *child = [NSEntityDescription insertNewObjectForEntityForName:@"Thread" inManagedObjectContext:[self moc]];
Thumbnail *thumb = [Thumbnail insertInManagedObjectContext:[self moc]];
Image *image = [Image insertInManagedObjectContext:[self moc]];
...
}
Эскиз и изображение являются подклассами NSManagedObject
генерируется с помощью генератора. insertInManagedObjectContext:
похоже
NSParameterAssert(moc_);
return [NSEntityDescription insertNewObjectForEntityForName:@"Thumbnail" inManagedObjectContext:moc_];
NSParameterAssert(moc_);
return [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:moc_];
The NSManagedObjectContext returned by [self moc] is created for the NSOperation with
NSPersistentStoreCoordinator *coord = [(MyApp_AppDelegate *)[[NSApplication sharedApplication] delegate] persistentStoreCoordinator];
self.moc = [[NSManagedObjectContext alloc] init];
[self.moc setPersistentStoreCoordinator:coord];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:self.moc];
[self.moc setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
[self.moc setUndoManager:nil];
[self.moc setRetainsRegisteredObjects:YES];
МОК определяется как (nonatomic, retain)
и синтезировать. Насколько я могу сказать, постоянный магазин и мой appDelegate
нет причин быть и не собирать мусор.
Трассировка стека выглядит так
Thread 2 Crashed: Dispatch queue: com.apple.root.default-priority
0 libauto.dylib 0x00007fff82d63600 auto_zone_root_write_barrier + 688
1 libobjc.A.dylib 0x00007fff826f963b objc_assign_strongCast_gc + 59
2 com.apple.CoreFoundation 0x00007fff88677068 __CFBasicHashAddValue + 504
3 com.apple.CoreFoundation 0x00007fff88676d2f CFBasicHashAddValue + 191
4 com.apple.CoreData 0x00007fff82bdee5e -[NSManagedObjectContext(_NSInternalAdditions) _insertObjectWithGlobalID:globalID:] + 190
5 com.apple.CoreData 0x00007fff82bded24 -[NSManagedObjectContext insertObject:] + 148
6 com.apple.CoreData 0x00007fff82bbd75c -[NSManagedObject initWithEntity:insertIntoManagedObjectContext:] + 716
7 com.apple.CoreData 0x00007fff82bdf075 +[NSEntityDescription insertNewObjectForEntityForName:inManagedObjectContext:] + 101
8 com.yourcompany.MyApp 0x000000010002c7a7 +[_Thumbnail insertInManagedObjectContext:] + 256 (_Thumbnail.m:14)
9 com.yourcompany.MyApp 0x000000010002672d -[ThreadParse main] + 10345 (ThreadParse.m:174)
10 com.apple.Foundation 0x00007fff85ee807e -[__NSOperationInternal start] + 698
11 com.apple.Foundation 0x00007fff85ee7d23 ____startOperations_block_invoke_2 + 99
12 libSystem.B.dylib 0x00007fff812bece8 _dispatch_call_block_and_release + 15
13 libSystem.B.dylib 0x00007fff8129d279 _dispatch_worker_thread2 + 231
14 libSystem.B.dylib 0x00007fff8129cbb8 _pthread_wqthread + 353
15 libSystem.B.dylib 0x00007fff8129ca55 start_wqthread + 13
Мое приложение падает в других местах с EXC_BAD_ACCESS, но это код, с которым это происходит чаще всего. Все трассировки стека выглядят одинаково и имеют отношение к CFHash
,
1 ответ
Если вы аварийно завершаете работу с exc_bad_access, это означает, что вы перевыпускаете объект или вызываете методы для объекта после его освобождения. Обе эти ситуации плохие и не имеют ничего общего с Core Data. Тот факт, что вы используете сборщик мусора, вероятно, является подсказкой того, что что-то разыменовывается и, следовательно, собирается мусором раньше, чем вы этого ожидаете.
Первый вопрос, хотя, вы создаете новый NSManagedObjectContext
для каждого из этих экземпляров NSOperation?
Во-вторых, я бы рекомендовал включить NSZombie
(что, я полагаю, вы можете сделать с помощью инструментов сейчас), и это поможет сузить, какой код вызывает объект после выпуска и т. д. Выполнение поиска Google в NSZombie
и инструменты появятся несколько статей с практическими рекомендациями.
Обновить
Так как это проблема 10.6 только тогда, это может иметь отношение к экземплярам NSOperation вместо экземпляров Core Data. Ваши операции помечены как параллельные? Причина, по которой я спрашиваю, состоит в том, что NSOperation игнорирует параллельный флаг на 10.6, и это может привести к некоторым неприятным сюрпризам.
обновление 2
Просто заметка, пока я рассматриваю общую проблему. Линия:
self.moc = [[NSManagedObjectContext alloc] init];
Утечка памяти (по крайней мере, когда GC выключен), если у вас нет выпуска, так как alloc init будет увеличивать счет сохранения, а затем вызов [self setMoc:] также увеличивает счет хранения.