Core Data and ARC crasher and workaround
Core Data and ARC crasher and workaround
- Subject: Core Data and ARC crasher and workaround
- From: Zac Bowling <email@hidden>
- Date: Tue, 03 Apr 2012 10:46:08 -0700
So I'm running into a crasher in iOS 5.0 and iOS 5.1 when using ARC with Core Data and wanted to warn everyone and give a possible fix. I'm filing radar on this but wanted to push it out there to list because it took me a while to track down exactly what the issue was from the crazy stack trace.
The crash happens below the dealloc and cxx_destruct method (that gets called by ARC) in a method named something around decrementing references to a managed object in the persistent store.
I've narrowed it down though.
If you have a NSManagedObjectContext reference in an object that is controlled by ARC and you have an NSManagedObject that is a member of that of that context that is also referenced by that same ARC controlled object, and you deference that object and it deallocs, if ARC deferences the NSManagedObjectContext before the NSManagedObject (the order is not determinate of releases unfortunately) and releases both about the same time in the same dealloc call, you will get a crash deep down inside core data.
This only happens when the context and the object references are released about the same time by ARC. I can't reproduce this without ARC.
If you override dealloc and do something like this it will take care of it (assuming you didn't have that context referenced anywhere else).
-(void) dealloc {
[_managedObjectContext reset];
}
This also seemed to work but it's hard in our cases because references are held by our child objects in many cases and it's not easy to always know who still my have a reference.
-(void) dealloc {
_objectFromContext = nil;
_managedObjectContext = nil;
}
I've also had this problem inside a single function scope where the context is dealloc at the end of the function. Nesting the references to the objects from that context in lower scopes or in blocks so the NSManagedObject references get dealloc'd before the context does solves the problem.
This is totally a hunch but I believe this is because of the magic with tagged pointers introduced with Lion possible and them not playing nice with ARC and the core data code. http://objectivistc.tumblr.com/post/7872364181/tagged-pointers-and-fast-pathed-cfnumber-integers-in . I think fault objects don't have a well defined strong reference to the context when they are not really there (just virtual tagged pointers) and I think optimizations in the ARC generated dealloc code get borked. Pure speculation but there is a lot of magic optimizations going on here now that may not be playing well together.
I think that many people don't run into this issue because they leave their contexts around for long periods and if they are making short lived ones they might not being using ARC. With parent/child contexts we create child contexts all the time to scope changed and NSUndoManagers to our modal popovers that have their own explicit save.
Here is the stack trace for google points and those that are curious:
EXC_BAD_ACCESS
#0 0x02475098 in objc_msgSend ()
#1 0x009e57f0 in _PFObjectIDFastHash64 ()
#2 0x020488a0 in __CFDictionaryHashKey ()
#3 0x01f9e0e4 in CFBasicHashFindBucket ()
#4 0x01f9daa5 in CFDictionaryGetValue ()
#5 0x009fde6a in -[NSPersistentStoreCache decrementRefCountForObjectID:] ()
#6 0x009fddf4 in -[NSSQLCore managedObjectContextDidUnregisterObjectsWithIDs:] ()
#7 0x00ab9fb6 in -[NSPersistentStoreCoordinator(_NSInternalMethods) _informAffectedStoresOfInterestByChildContextInObjectsWithObjectIDs:withSelector:] ()
#8 0x009fdcff in -[NSPersistentStoreCoordinator(_NSInternalMethods) managedObjectContextDidUnregisterObjectsWithIDs:] ()
#9 0x00a27099 in __-[NSManagedObjectContext(_NestedContextSupport) managedObjectContextDidUnregisterObjectsWithIDs:]_block_invoke_1 ()
#10 0x00a24051 in internalBlockToNSManagedObjectContextPerform ()
#11 0x01f45951 in _dispatch_barrier_sync_f_invoke ()
#12 0x01f45e00 in dispatch_barrier_sync_f ()
#13 0x00a23ff5 in _perform ()
#14 0x00a27049 in -[NSManagedObjectContext(_NestedContextSupport) managedObjectContextDidUnregisterObjectsWithIDs:] ()
#15 0x00a27099 in __-[NSManagedObjectContext(_NestedContextSupport) managedObjectContextDidUnregisterObjectsWithIDs:]_block_invoke_1 ()
#16 0x00a23fd4 in _perform ()
#17 0x00a27049 in -[NSManagedObjectContext(_NestedContextSupport) managedObjectContextDidUnregisterObjectsWithIDs:] ()
#18 0x00a31665 in -[NSManagedObjectContext(_NSInternalAdditions) _disposeObjects:count:notifyParent:] ()
#19 0x00a30bb3 in -[NSManagedObjectContext(_NSInternalAdditions) _dispose:] ()
#20 0x00a30756 in -[NSManagedObjectContext _dealloc__] ()
#21 0x00a30616 in -[NSManagedObjectContext dealloc] ()
#22 0x009f4961 in -[NSManagedObjectContext release] ()
#23 0x02475e00 in objc_release ()
#24 0x02477047 in objc_storeStrong ()
#25 0x000d1bb3 in -[SMGuestInfoEditController .cxx_destruct] at /Users/zbowling/projects/dorsia/Dorsia/iOS/iPad/SMGuestInfoEditController.m:108
#26 0x0246130d in object_cxxDestructFromClass ()
#27 0x0246bfde in objc_destructInstance ()
#28 0x0246c015 in object_dispose ()
#29 0x020889a1 in -[NSObject dealloc] ()
#30 0x00d63f5e in -[UIViewController dealloc] ()
#31 0x00ecf296 in -[UITableViewController dealloc] ()
#32 0x000be8f6 in -[SMGuestInfoEditController dealloc] ()
#33 0x02475e3d in _objc_rootRelease ()
#34 0x02475e00 in objc_release ()
#35 0x00cd8953 in __destroy_helper_block_1084 ()
#36 0x01f0c55d in _Block_release ()
#37 0x00cd75df in -[UIViewAnimationBlockDelegate dealloc] ()
#38 0x02475e3d in _objc_rootRelease ()
#39 0x01f92405 in CFRelease ()
#40 0x02048ac0 in __CFDictionaryStandardReleaseValue ()
#41 0x01fa9481 in __CFBasicHashDrain ()
#42 0x01f924b3 in CFRelease ()
#43 0x02475e00 in objc_release ()
#44 0x02476c50 in (anonymous namespace)::AutoreleasePoolPage::pop(void*) ()
#45 0x01fbaea8 in _CFAutoreleasePoolPop ()
#46 0x01fbd80b in __CFRunLoopRun ()
#47 0x01fbcd84 in CFRunLoopRunSpecific ()
#48 0x01fbcc9b in CFRunLoopRunInMode ()
#49 0x029157d8 in GSEventRunModal ()
#50 0x0291588a in GSEventRun ()
#51 0x00c9d626 in UIApplicationMain ()
#52 0x0000620d in main ()
--
Zac Bowling
_______________________________________________
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