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:] также увеличивает счет хранения.

Другие вопросы по тегам