2

私が抱えている問題の最小限のコード例を書きました。バックグラウンド作業を 2 つの方法で実装しました。スレッドを手動で生成する方法と、スレッドNSOperation処理を処理する方法です。どちらの場合もNSManagedObjectContexts、スレッド/操作ごとに作成しています。

自分でスレッドを生成すると、performSelectorInBackground:withObject:すべて正常に動作します。オブジェクトを に渡すように切り替えるとNSOperationQueue、操作を保存しようとすると、次のエラーが表示されますNSManagedObjectContext

-EXC_BAD_ACCESS - 重大なアプリケーション エラーです。Core Data 変更処理中に例外がキャッチされました: *** -[NSCFSet addObject:]: userInfo (null) で nil を挿入しようとしています - _referenceData64 は抽象クラスに対してのみ定義されています。-[NSTemporaryObjectID_default_referenceData64] を定義してください!

特に最後のエラーを考えると、バグは、スレッド/コンテキスト間でオブジェクトを渡すために一時的な objectID を使用することに関係していると思います。さらに悪いことに、私はどういうわけかNSManagedObjectsスレッド間を行き来しています。

いずれにせよ、そうしていることを示唆するコードが見つかりません。

私の最小限のコード例はここにあります。

ほとんどの作業は で行われAppDelegateますawakeFromNibEXECUTE_WITH_NSOPERATIONで実行するには 0 に設定しperformSelectorInBackground:withObject:ます。一連のオブジェクトを作成する でEXECUTE_WITH_NSOPERATION実行するには、1 のままにします。NSOperationQueueMCBoardParse

これは10.6未満でしか見られません。

オリジナル

10.5 フレームワークで構築された Cocoa アプリケーションがあります。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]];
  ...
 }

Thumbnail と Image はどちらもNSManagedObjectmogenerator で生成されたサブクラスです。 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];

moc は次のように定義され(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.

4

1 に答える 1

1

exc_bad_access でクラッシュしている場合は、オブジェクトを過剰に解放しているか、オブジェクトが解放された後にメソッドを呼び出していることを意味します。これらの状況は両方とも良くなく、Core Data とは何の関係もありません。ガベージ コレクションを使用しているという事実は、おそらく、何かが逆参照されているため、期待する前にガベージ コレクションが行われているという手掛かりです。

最初の質問ですが、NSManagedObjectContextこれらの NSOperation インスタンスごとに新しいものを作成していますか?

次に、オンにすることをお勧めします (これは、現在インストゥルメントを使用して実行できると思います)。これにより、リリース後にどのコードがオブジェクトを呼び出しているかNSZombieを絞り込むことができます。NSZombie.

アップデート

これは 10.6 のみの問題であるため、Core Data インスタンスではなく NSOperation インスタンスに関係している可能性があります。操作は並行としてフラグが立てられていますか? 私が尋ねる理由は、NSOperation が 10.6 の同時実行フラグを無視し、それが厄介な驚きにつながる可能性があるためです。

更新 2

全体的な問題を確認している間のメモです。この線:

self.moc = [[NSManagedObjectContext alloc] init];

alloc init が保持カウントをインクリメントし、[self setMoc:] 呼び出しも保持カウントをインクリメントするため、リリースがない場合は (少なくとも GC がオフの間は) メモリ リークが発生します。

于 2010-03-20T17:05:46.960 に答える