简体   繁体   中英

iOS app crashes with objc_release EXC_BAD_ACCESS on startup

My app keeps (which uses ARC) crashes right after startup, with the following backtraces of the threads:

在此处输入图片说明

在此处输入图片说明

The weird thing is that when I try to run the app with Instruments-Zombie tool, the app works fine and doesn't crash, but I get no zombie accessed notification on the instrument panel. If it works fine with zombies flag enabled, I would at least expect to see one zombie notification!

Any ideas on how to further approach this issue?

Edit

So here is some code, and I've managed to narrow the problem to a specific code path.

XYZStore.h/m:

@property (nonatomic,strong,readonly) NSManagedObjectContext* mainManagedObjectContext;

@implementation XYZStore

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"MyApp.sqlite"];

    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
    return _persistentStoreCoordinator;
}

- (NSManagedObjectContext *)mainManagedObjectContext
{
    if (_mainManagedObjectContext != nil) {
        return _mainManagedObjectContext;
    }

    _mainManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    _mainManagedObjectContext.persistentStoreCoordinator = [self persistentStoreCoordinator];
    return _mainManagedObjectContext;
}

Initial view controller:


-(void)awakeFromNib
{
    XYZAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
    NSManagedObjectContext *moc= delegate.store.mainManagedObjectContext; // managed context object from XYZStore

    NSEntityDescription *entityDescription = [NSEntityDescription
                                              entityForName:@"Person" inManagedObjectContext:moc];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];

    [request setEntity:entityDescription];

    NSError *error;
    NSArray *results = [moc executeFetchRequest:request error:&error];
    for (id *obj in results) {
        NSLog(@"%p", obj);
    }
    NSLog(@"%d", [results count]); // print "232"
}

This code path throws the exception I attached above (objc_release).

Two important things I've noticed:

1) If I insert [moc reset] after the fetch, the exception is not raised anymore (this is of course not scalable for my program, as I am dealing with NSFetchRequestControllers and such).

2) If I don't use the main object context, but a an object context in a private queue, then the exception is not raised as well.

Full backtrace:

(lldb) thread backtrace

  • thread #1: tid = 0x9c9a, 0x03b39e85 libobjc.A.dylib objc_release + 21, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xd0000010) * frame #0: 0x03b39e85 libobjc.A.dylib objc_release + 21 frame #1: 0x03b3ad32 libobjc.A.dylib (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 586 frame #2: 0x04153678 CoreFoundation _CFAutoreleasePoolPop + 24 frame #3: 0x01123184 Foundation -[NSAutoreleasePool drain] + 149 frame #4: 0x0379a9ec CoreData _performRunLoopAction + 348 frame #5: 0x041949de CoreFoundation` CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION
  • 30 frame #6: 0x04194920 CoreFoundation __CFRunLoopDoObservers + 400 frame #7: 0x0418a35a CoreFoundation __CFRunLoopRun + 1226 frame #8: 0x04189bcb CoreFoundation CFRunLoopRunSpecific + 443 frame #9: 0x041899fb CoreFoundation CFRunLoopRunInMode + 123 frame #10: 0x05c4d24f GraphicsServices GSEventRunModal + 192 frame #11: 0x05c4d08c GraphicsServices GSEventRun + 104 frame #12: 0x01de48b6 UIKit UIApplicationMain + 1526 frame #13: 0x000611cd Contacit main(argc=1, argv=0xbfff83b0) + 141 at main.m:16 frame #14: 0x0482cac9 libdyld.dylib`start + 1

So any help in the investigation would be very much appreciated!

Apparently this was the cause to the problem... In my extended NSManagedObject class I had overriden this method

- (void)willTurnIntoFault
{
    [super willTurnIntoFault];

    if ([self observationInfo])
    {
        NSLog(@"%@ has observers:\n%@", [self objectID], [self observationInfo]);
    }
}

Removing this fixed the issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM