NSManagedObjects, die ich besitze, werden von main.m veröffentlicht?
Zunächst initialisiere ich in meinen Stammansichts-Controllern viewDidLoad ein NSDictionary mit Arrays von NSManagedObjects wie folgt:
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"Decks";
UIBarButtonItem *browseButton = [[UIBarButtonItem alloc] initWithTitle:@"Browse" style:UIBarButtonItemStylePlain target:self action:@selector(loadBrowseView)];
self.navigationItem.rightBarButtonItem = browseButton;
[browseButton release];
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
}
self.categories = [fetchedResultsController fetchedObjects];
NSMutableDictionary *tipsMutableDictionary = [[NSMutableDictionary alloc] init];
for (Category *category in self.categories) {
NSMutableArray *tipsToSort = [NSMutableArray arrayWithArray:[[category valueForKey:@"tips"] allObjects]];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending: YES];
[tipsToSort sortUsingDescriptors: [NSArray arrayWithObject: sortDescriptor]];
[sortDescriptor release];
[tipsMutableDictionary setObject:[NSArray arrayWithArray:tipsToSort] forKey:[category name]];
}
self.tips = tipsMutableDictionary;
[tipsMutableDictionary release];
}
Jetzt ist "self.tips", eine beibehaltene NSDictionary-Eigenschaft auf meinem Stammansichts-Controller, so eingerichtet, dass sie Arrays von NSManagedObjects enthält. Ich benutze diese Daten gerne etwa 5 Minuten lang (einschließlich der Weitergabe an die beibehaltenen Eigenschaften anderer Ansichten), bis die folgende Meldung angezeigt wird:
malloc: *** error for object 0x3b300b0: double free
In diesem Moment, nach dem Fehler, aber vor dem tatsächlichen Absturz, sieht die Rückverfolgung wie folgt aus:
#0 0x98152072 in malloc_error_break ()
#1 0x98153218 in szone_error ()
#2 0x9815334d in free_tiny_botch ()
#3 0x01b83064 in _PFDeallocateObject ()
#4 0x01b8d315 in -[_PFManagedObjectReferenceQueue _processReferenceQueue:] ()
#5 0x01bba9ba in _performRunLoopAction ()
#6 0x01d42252 in __CFRunLoopDoObservers ()
#7 0x01d4165f in CFRunLoopRunSpecific ()
#8 0x01d40c48 in CFRunLoopRunInMode ()
#9 0x0252d615 in GSEventRunModal ()
#10 0x0252d6da in GSEventRun ()
#11 0x002a3faf in UIApplicationMain ()
#12 0x00002830 in main (argc=1, argv=0xbfffef60) at /Users/***/main.m:14
Bemerkenswerterweise gibt es dort keinen Code von mir.
Ein Druckobjekt auf 0x3b300b0 enthüllt:
<Tip: 0x3b300b0> (entity: Tip; id: 0x3b2ffe0 <x-coredata://10B4E6EE-ACF3-4316-AE10-6E06E8FFFF46/Tip/p9> ; data: <fault>)
Und am interessantesten ist die Shell malloc_history an dieser Adresse:
ALLOC 0x3b300b0-0x3b300ef [size=64]: thread_a0a3f500 |start | main | UIApplicationMain | -[UIApplication _run] | CFRunLoopRunInMode | CFRunLoopRunSpecific | PurpleEventCallback | _UIApplicationHandleEvent | -[UIApplication sendEvent:] | -[UIApplication handleEvent:withNewEvent:] | -[UIApplication _reportAppLaunchFinished] | CA::Transaction::commit() | CA::Context::commit_transaction(CA::Transaction*) | CALayerLayoutIfNeeded | -[CALayer layoutSublayers] | -[UILayoutContainerView layoutSubviews] | -[UINavigationController _startDeferredTransitionIfNeeded] | -[UINavigationController _startTransition:fromViewController:toViewController:] | -[UINavigationController _layoutViewController:] | -[UINavigationController _computeAndApplyScrollContentInsetDeltaForViewController:] | -[UIViewController contentScrollView] | -[UIViewController view] | -[RootViewController viewDidLoad] | -[_NSFaultingMutableSet allObjects] | -[_NSFaultingMutableSet willRead] | -[NSManagedObjectContext(_NSInternalAdditions) _retainedObjectWithID:optionalHandler:withInlineStorage:] | +[NSManagedObject(_PFDynamicAccessorsAndPropertySupport) allocWithEntity:] | _PFAllocateObject | malloc_zone_calloc
----
FREE 0x3b300b0-0x3b300ef [size=64]: thread_a0a3f500 |start | main | UIApplicationMain | GSEventRun | GSEventRunModal | CFRunLoopRunInMode | CFRunLoopRunSpecific | __CFRunLoopDoObservers | _performRunLoopAction | -[_PFManagedObjectReferenceQueue _processReferenceQueue:] | -[NSManagedObjectContext(_NSInternalAdditions) _forgetObject:propagateToObjectStore:] | -[NSManagedObjectContext(_NSInternalAdditions) _forgetObject:propagateToObjectStore:removeFromRegistry:] | CFDictionaryRemoveValue | CFRelease | _PFDeallocateObject | malloc_zone_free
ALLOC 0x3b300b0-0x3b300cf [size=32]: thread_a0a3f500 |start | main | UIApplicationMain | GSEventRun | GSEventRunModal | CFRunLoopRunInMode | CFRunLoopRunSpecific | __CFRunLoopDoObservers | _performRunLoopAction | -[_PFManagedObjectReferenceQueue _processReferenceQueue:] | _PFDeallocateObject | free_tiny_botch | szone_error | start | _NSPrintForDebugger | -[NSManagedObject description] | +[NSString stringWithFormat:] | -[NSPlaceholderString initWithFormat:locale:arguments:] | _CFStringCreateWithFormatAndArgumentsAux | CFStringCreateMutable | _CFRuntimeCreateInstance | malloc_zone_malloc
Meine Interpretation des oben Gesagten ist, dass "[RootViewController viewDidLoad]" in der ersten ALLOC-Anweisung bedeutet, dass ich die Tipps von NSDictionary anfänglich mit Daten fülle. In der folgenden FREE-Anweisung beschließt main.m, diese Objekte freizugeben, obwohl sie sich in einem beibehaltenen NSDictionary befinden, für dessen Freigabe ich verantwortlich bin.
BEARBEITEN Pro Anfrage ist hier die Ausgabe von NSZombieEnabled:
*** -[CFString retain]: message sent to deallocated instance 0x3b300b0
Zurückverfolgen danach:
#0 0x01d6a3a7 in ___forwarding___ ()
#1 0x01d466c2 in __forwarding_prep_0___ ()
#2 0x01cfd988 in CFRetain ()
#3 0x01cfd495 in CFArrayCreate ()
#4 0x01d406c3 in -[__NSPlaceholderArray initWithObjects:count:] ()
#5 0x01d4f6f8 in -[NSArray initWithArray:copyItems:] ()
#6 0x01d5c408 in +[NSArray arrayWithArray:] ()
#7 0x0000392f in -[RootViewController getRandomTip:] (self=0x3e1db40, _cmd=0x745b, sender=0x3e27d60) at /Users/***/RootViewController.m:32
#8 0x00299405 in -[UIApplication sendAction:to:from:forEvent:] ()
#9 0x002fcb4e in -[UIControl sendAction:to:forEvent:] ()
#10 0x002fed6f in -[UIControl(Internal) _sendActionsForEvents:withEvent:] ()
#11 0x002fdabb in -[UIControl touchesEnded:withEvent:] ()
#12 0x002b2ddf in -[UIWindow _sendTouchesForEvent:] ()
#13 0x0029c7c8 in -[UIApplication sendEvent:] ()
#14 0x002a3061 in _UIApplicationHandleEvent ()
#15 0x0252ed59 in PurpleEventCallback ()
#16 0x01d41b80 in CFRunLoopRunSpecific ()
#17 0x01d40c48 in CFRunLoopRunInMode ()
#18 0x0252d615 in GSEventRunModal ()
#19 0x0252d6da in GSEventRun ()
#20 0x002a3faf in UIApplicationMain ()
#21 0x00002830 in main (argc=1, argv=0xbfffef60) at /Users/***/main.m:14
Die Codezeile, auf die von oben verwiesen wird (/Users/***/RootViewController.m:32), lautet:
NSArray *tipsArray = [NSArray arrayWithArray:[self.tips objectForKey:categoryNameString]];
Ich kann nur sagen, dass die Objekte, auf die ich über "self.tips" zugreifen möchte, bereits freigegeben wurden (von wem? Und warum?).