Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Odd Core Data error caused by over releasing?

Occasional reader and first time question asker, so please be gentle :)

I am creating a Managed Object (Account), that is being passed into a child view controller where its being set in a property that is retained.

Account * account = [[Account alloc] initWithEntity:entity insertIntoManagedObjectContext:context];
AddAccountViewController *childController = [[AddAccountViewController alloc] init];
childController.title = @"Account Details"; 
childController.anAccount = account;
childController.delegate = self;

[self.navigationController pushViewController:childController animated:YES];
[childController release];
[account release];

The view controller interface:

@interface AddAccountViewController : UIViewController {
}

@property (nonatomic, retain) IBOutlet UITextField * usernameTextField;
@property (nonatomic, retain) IBOutlet UITextField * passwordTextField;

@property (nonatomic, retain) Account * anAccount;
@property (nonatomic, assign) id <AddAccountDelegate> delegate;

- (IBAction)cancel:(id)sender;
- (IBAction)add:(id)sender;
- (IBAction)textFieldDone:(id)sender;
@end

So in code sample 1 I've released the account object because I am no longer interested in it in that method. As it is retained by the AddAccountViewController I have an entry in AddAccountViewController's dealloc that releases it.

However when I go to delete the object from the ManagedObjectContext the app crashes with the following (rather unclear) error:

Detected an attempt to call a symbol in system libraries that is not present on the iPhone:
_Unwind_Resume called from function _PFFaultHandlerLookupRow in image CoreData.

After much debugging & hair pulling I discovered that if I don't release account in AddAccountViewController's dealloc method the app works properly continually and doesn't appear to leak according to Instruments.

Can anyone shed any light as to whats going on? I understand from the docs on properties that those retained need to be released. What have I missed?

Update to answer Kevin's question

The code to delete the object from the ManagedObjectContext is in the RootViewController (that holding the child controller)

// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the managed object for the given index path
        NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];

        [context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];

        // Save the context.
        NSError *error = nil;
        if (![context save:&error]) {
            /*
             Replace this implementation with code to handle the error appropriately.

             abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
             */
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }  
}
like image 406
tarasis Avatar asked Sep 12 '10 09:09

tarasis


2 Answers

Firstly: It sounds like a bug on Apple's part. Core Data is calling _Unwind_Resume, which is (probably) some sort of exception unwind. Exception-unwinding exists on the phone, but (I think) uses the ARM ABI, which uses function names beginning with __cxa_. Are you running on the simulator? Which version of the SDK?

There might be an extra release floating around somewhere which is "balanced" when you remove the call to [account release];.

"Instruments doesn't show any leaks" doesn't mean there aren't any; last I checked it got confused by cycles (i.e. it wouldn't show a leak if you forgot to un-set IBOutlets in dealloc). I tested with NSMutableData * d = [NSMutableData dataWithLength:1<<20]; memcpy(d.mutableBytes, &d, 4);, but an easier test is just [[UIView alloc] initWithFrame:CGRectZero].

If you think it's a retain/release issue, I once debugged these by overriding retain/release/autorelease to call NSLog. I then added breakpoints on all of them, set them to run the command "bt", and clicked the autocontinue. Then run the thing that breaks (in my case I think it was just an extra retain), print out the log output,stick it on a whiteboard, and spend half an hour matching retains and releases.

like image 196
tc. Avatar answered Sep 19 '22 08:09

tc.


I had a similar issue ending in a "Detected an attempt to call a symbol in system libraries that is not present on the iPhone: _Unwind_Resume called from function _PFFaultHandlerLookupRow in image CoreData." error message.

My problem was a wrong "cascading" deletion-rule on a relation in the model. With this rule, my top managed object got deleted but still referenced in the code. After setting the "delete rule" on this relation to "nulify", everything worked as designed.

--> no core data issue...design issue!

Johnny

like image 1
Johnny Avatar answered Sep 22 '22 08:09

Johnny