使用EXC_BAD_ACCESS(SIGSEGV)和ARM线程状态(64位)调查iOS崩溃报告

时间:2014-09-02 14:39:38

标签: ios core-data crash nsfetchedresultscontroller nsmanagedobjectcontext

我最近在App Store中发布了对我应用的更新。测试没有发生崩溃,但我注意到它在App Store中发布时,一个场景在我的5s上崩溃了我的应用程序。这种情况在开发过程中没有崩溃。我收到了一个用户的报告,说它在5s的一个场景中也崩溃了,这跟我正在做的一样。

我正处于iOS开发的中间阶段,这是我诊断崩溃报告的第一次经历。

更新:请滚动到问题的底部以获取有关问题的进一步更新

在Xcode中,我的5s上的应用程序有以下崩溃报告:

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000060
Triggered by Thread:  0

Thread 0 Crashed:
0   CoreData                        0x00000001822f8af4 _propertyAtIndexForEntityDescription + 24
1   CoreData                        0x00000001822f0330 snapshot_get_value_as_object + 304
2   Foundation                      0x0000000183080a78 -[NSObject(NSKeyValueCoding) valueForKeyPath:] + 288
3   Foundation                      0x00000001831613cc -[NSSortDescriptor compareObject:toObject:] + 140
4   CoreData                        0x0000000182305d9c +[NSFetchedResultsController(PrivateMethods) _insertIndexForObject:inArray:lowIdx:highIdx:sortDescriptors:] + 284
5   CoreData                        0x00000001823dd808 -[NSFetchedResultsController(PrivateMethods) _createNewSectionForObject:] + 492
6   CoreData                        0x0000000182305b58 -[NSFetchedResultsController(PrivateMethods) _postprocessInsertedObjects:] + 528
7   CoreData                        0x00000001823025f8 -[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:] + 2036
8   CoreFoundation                  0x000000018259b760 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 16
9   CoreFoundation                  0x00000001824e82b0 _CFXNotificationPost + 2060
10  Foundation                      0x000000018307a744 -[NSNotificationCenter postNotificationName:object:userInfo:] + 68
11  CoreData                        0x0000000182301dd8 -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] + 84
12  CoreData                        0x0000000182301d58 -[NSManagedObjectContext(_NSInternalChangeProcessing) _createAndPostChangeNotification:withDeletions:withUpdates:withRefreshes:] + 360
13  CoreData                        0x0000000182300348 -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] + 2224
14  CoreData                        0x00000001822ff264 -[NSManagedObjectContext save:] + 152
15  Lopey                       0x000000010004da3c -[LopeyAddEntryViewController save:] (LopeyAddEntryViewController.m:828)
16  UIKit                           0x00000001855e50ac -[UIApplication sendAction:to:from:forEvent:] + 96
17  UIKit                           0x00000001855e50ac -[UIApplication sendAction:to:from:forEvent:] + 96
18  UIKit                           0x00000001855e5040 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 20
19  UIKit                           0x00000001855ce51c -[UIControl _sendActionsForEvents:withEvent:] + 372
20  UIKit                           0x00000001855e4a40 -[UIControl touchesEnded:withEvent:] + 580
21  UIKit                           0x00000001855e46d4 -[UIWindow _sendTouchesForEvent:] + 688
22  UIKit                           0x00000001855df36c -[UIWindow sendEvent:] + 1168
23  UIKit                           0x00000001855b0b4c -[UIApplication sendEvent:] + 252
24  UIKit                           0x00000001855aec3c _UIApplicationHandleEventQueue + 8496
25  CoreFoundation                  0x00000001825a77f0 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 20
26  CoreFoundation                  0x00000001825a6b4c __CFRunLoopDoSources0 + 252
27  CoreFoundation                  0x00000001825a4de4 __CFRunLoopRun + 628
28  CoreFoundation                  0x00000001824e5dcc CFRunLoopRunSpecific + 448
29  GraphicsServices                0x00000001881cdc08 GSEventRunModal + 164
30  UIKit                           0x0000000185616fc0 UIApplicationMain + 1152
31  Lopey                       0x000000010005a40c main (main.m:16)
32  libdyld.dylib                   0x000000018f0e3a9c start + 0

我还有一点下来:

Thread 0 crashed with ARM Thread State (64-bit):
    x0: 0x0000000000000000   x1: 0x0000000000000000   x2: 0x0000000000000000   x3: 0x0000000000000000
    x4: 0x0000000000000001   x5: 0x0000000000000074   x6: 0x0000000000000074   x7: 0x0000000000000000
    x8: 0x0000000000000060   x9: 0x0000000000000020  x10: 0x0000000100124540  x11: 0x000000100000001f
   x12: 0x00000001001245a0  x13: 0x0000000178242d60  x14: 0x0000000000000034  x15: 0x0000000004060401
   x16: 0x000000018a1c96e6  x17: 0x000000018234e2d4  x18: 0x0000000000000000  x19: 0x0000000000000000
   x20: 0x000000017043b580  x21: 0x0000000000000011  x22: 0x000000017043c1e0  x23: 0x0000000000000006
   x24: 0x000000018265d35b  x25: 0x000000018f715000  x26: 0x000000018f715000  x27: 0x0000000000000002
   x28: 0x00000001780dbd60  fp: 0x000000016fdfc850   lr: 0x00000001822f0334
    sp: 0x000000016fdfc840   pc: 0x00000001822f8af4 cpsr: 0x60000000

从日志中可以看出,我正在Core Data使用NSFetchedResultsController。我有一个UITableViewController因用户点击UINavigationBar中的按钮而被填充,将一些条目添加到几个UITextField并按“保存”。这就是崩溃的一点。但是,我必须提到它每次都不会崩溃。实际上,在崩溃之前,我已经连续添加了45个条目,之后我添加了100个没有崩溃。它只发生过一次。

应用程序中崩溃的点是我按下保存(这将关闭ViewController并返回UITableView。考虑到这一点,它要么是实际的“保存” “NSManagedObjectContext中的,或者是UITableView的加载。我的钱是前者,但我不太确定。

以下是NSManagedObjectContextApp Delegate的代码:

- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];

    if (coordinator != nil) {
        NSManagedObjectContext* moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
        moc.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;

        [moc setPersistentStoreCoordinator: coordinator];

        _managedObjectContext = moc;
    }

    return _managedObjectContext;
}

以下是Save中的App Delegate方法:

- (void)saveContext
{
    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) {
        if ([managedObjectContext hasChanges] && ![managedObjectContext 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.
            //NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }
}

如上所述,我对开发还很陌生,这是我第一次看到需要调查的崩溃日志。这方面的任何方向都会受到赞赏。它是否也与5s中的64位处理器有关? (也许这可以解释为什么我不能在其他地方重现它?)。

更新1

我的应用仅限iOS 7。我的5s只是iOS 7,我已经在iOS 8上测试了我的应用程序,但是在4s上没有遇到类似的崩溃。此外,我也在iPad Mini上测试过,所以这只是iPhone 5s的问题。

更新2

显示保存下面新对象的代码。它可能看起来很复杂,但基本上名称,事件等基于自动完成,该自动完成基于哪些对象已经存在于核心数据中等。

- (IBAction)save:(id)sender
{
    NSManagedObjectContext *context = [self managedObjectContext];

    // Insert a new transaction
    Transaction *transaction = [NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:context];
    Item *itemType = [NSEntityDescription insertNewObjectForEntityForName:@"Item" inManagedObjectContext:context];

    itemType.amount = self.itemTextField.text;
    transaction.item = itemType;
    transaction.wasReceived = @(self.isReceivedSegment.selectedSegmentIndex == 0);

    Person *enteredPerson = (Person *)[Person personWithName:self.nameTextField.text inManagedObjectContext:context];
    transaction.whoBy = enteredPerson;

    Occasion *enteredOccasion = (Occasion *)[Occasion occasionWithTitle:self.occasionTextField.text inManagedObjectContext:context];
    transaction.occasion = enteredOccasion;

    Subevent *enteredSubevent = (Subevent *)[Subevent subeventWithTitle:self.subeventTextField.text inManagedObjectContext:context];
    transaction.subevent = enteredSubevent;

    NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *components = [cal components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit
                                          fromDate:self.datePicker.date];
    [components setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
    NSDate *selectedDate = [cal dateFromComponents:components];

    Date *date = (Date *)[Date occasionWithDate:selectedDate inManagedObjectContext:context];
    transaction.dates = date;

    NSError *error = nil;
    if (![context save:&error])
    {
        // Error
    }

    [self dismissViewControllerAnimated:YES completion:nil];
}

在UITableViewController中,我的fetchedResultsController位于:

- (NSFetchedResultsController *)fetchedResultsController
{
    NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
    if (_fetchedResultsController != nil)
    {
        return _fetchedResultsController;
    }
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Transaction" inManagedObjectContext:managedObjectContext];
    fetchRequest.entity = entity;

    // I am implementing a search here so we can either search by name or event with the prediate filtering out the information.
    if ([self.timelineSearchBar.text length] > 0) {
        NSPredicate *predName = [NSPredicate predicateWithFormat:@"whoBy.name CONTAINS[c] %@", self.timelineSearchBar.text];
        NSPredicate *predOccasion = [NSPredicate predicateWithFormat:@"occasion.title CONTAINS[c] %@", self.timelineSearchBar.text];

        // Adding in another predicate for searching by subevent
        NSPredicate *predSubOccasion = [NSPredicate predicateWithFormat:@"subevent.title CONTAINS[c] %@", self.timelineSearchBar.text];

        // creating the orCompoundPredicate for the two conditions
        NSPredicate *compPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[predName, predOccasion, predSubOccasion]];

        [fetchRequest setPredicate:compPredicate];
    }
    // Sorting by date and by name.
    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"dates.dateOfEvent" ascending:NO];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"whoBy.name" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];

    fetchRequest.sortDescriptors = @[sort, sortDescriptor];

    fetchRequest.fetchBatchSize = 20;
    NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"sectionDateFormatter" cacheName:nil];
    self.fetchedResultsController = theFetchedResultsController;
    _fetchedResultsController.delegate = self;
    return _fetchedResultsController;
}

希望这有用!

更新3

我想尝试重现这个问题。第一次重现的步骤涉及从先前版本的应用程序进行更新。在更新之前,我的设备上有App Store版本,当更新发布时,我更新到了那个,创建了一个新条目,这就是它崩溃的一点。我运行了我的应用程序的旧版本,并在Xcode中升级到这个新版本,当应用程序升级并准备好时,我添加了一个新条目和一个异常断点,它在transaction.dates = date崩溃了;在上面列出的Save方法中,在更新2中。断点报告:Thread 1: EXC_BAD_ACCESS (code=1,address=0x60)

我再次执行了这些步骤,没有断点,并且在相同的代码行停止并出现相同的错误。

更新4

如果我将应用更新到最新版本并立即添加新条目,则只会发生此崩溃。但是,如果我在添加新条目之前重新运行应用程序,则设备不会崩溃。

更新5

通过一些进一步的测试,我发现这次崩溃是因为只在iPhone 5s和iPad Air上更新到这个新版本。该应用程序不会在任何其他设备上崩溃。有了这个最新版本的应用程序,我带来了iCloud同步。在App Delegate中,我在下面的代码将在用户选择在更新教程中选择使用iCloud时运行。正是在这种情况下,应用程序崩溃了。

- (void)initialMigrationOfLocalDataToiCloud
{    
    NSURL *storeURL = [self.persistentStoreCoordinator.persistentStores.lastObject URL];

    NSPersistentStore *currentStore = self.persistentStoreCoordinator.persistentStores.lastObject;

    NSURL *cloudURL = [self grabCloudPath:@"CloudLogs"];
    NSString *cloudStoreTitle = @"LopeyCloud";

    NSDictionary *options = @{NSPersistentStoreUbiquitousContentURLKey: cloudURL,
                              NSPersistentStoreUbiquitousContentNameKey: cloudStoreTitle,                               NSMigratePersistentStoresAutomaticallyOption : @YES,
                              NSInferMappingModelAutomaticallyOption : @YES};

    [self.persistentStoreCoordinator migratePersistentStore:currentStore toURL:storeURL options:options withType:NSSQLiteStoreType error:nil];

}

我在那里进行了轻量级迁移,因为用户可能正在从以前的版本等进行更新。

设置了异常断点(即使没有它),根据 Update 2 ,应用会在transaction.dates = date;方法的save代码中崩溃。我不允许跳出代码或对此做任何事情。通过调试器,我看不出transaction.dates的值是什么,但date不是零。即使我没有设置断点,应用程序也会在此处的同一行代码中崩溃。

我希望这是有道理的。

0 个答案:

没有答案