iOS 应用在启动时崩溃 objc_release EXC_BAD_ACCESS
iOS app crashes with objc_release EXC_BAD_ACCESS on startup
我的应用程序(使用 ARC)在启动后立即崩溃,线程的回溯如下:
奇怪的是,当我尝试使用 Instruments-Zombie 工具 运行 应用程序时,应用程序工作正常并且没有崩溃,但我在仪表板上没有收到僵尸访问通知.如果它在启用僵尸标志的情况下工作正常,我至少希望看到一个僵尸通知!
关于如何进一步处理这个问题有什么想法吗?
编辑
所以这里有一些代码,我已经设法将问题缩小到特定的代码路径。
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"
}
此代码路径抛出我在上面附加的异常 (objc_release)。
我注意到两件重要的事情:
1) 如果我在提取后插入 [moc reset]
,则不再引发异常(这当然不能扩展我的程序,因为我正在处理 NSFetchRequestControllers 等)。
2) 如果我不使用主对象上下文,而是使用私有队列中的对象上下文,那么也不会引发异常。
完整回溯:
(lldb) 线程回溯
- 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 CoreFoundationCFRunLoopRunSpecific + 443
frame #9: 0x041899fb CoreFoundation
CFRunLoopRunInMode + 123
frame #10: 0x05c4d24f GraphicsServicesGSEventRunModal + 192
frame #11: 0x05c4d08c GraphicsServices
GSEventRun + 104
frame #12: 0x01de48b6 UIKitUIApplicationMain + 1526
frame #13: 0x000611cd Contacit
main(argc=1, argv=0xbfff83b0) + 141 at main.m:16
frame #14: 0x0482cac9 libdyld.dylib`start + 1
非常感谢调查中的任何帮助!
显然这是问题的原因...在我的扩展 NSManagedObject class 中我重写了这个方法
- (void)willTurnIntoFault
{
[super willTurnIntoFault];
if ([self observationInfo])
{
NSLog(@"%@ has observers:\n%@", [self objectID], [self observationInfo]);
}
}
删除这个问题解决了这个问题。
我的应用程序(使用 ARC)在启动后立即崩溃,线程的回溯如下:
奇怪的是,当我尝试使用 Instruments-Zombie 工具 运行 应用程序时,应用程序工作正常并且没有崩溃,但我在仪表板上没有收到僵尸访问通知.如果它在启用僵尸标志的情况下工作正常,我至少希望看到一个僵尸通知!
关于如何进一步处理这个问题有什么想法吗?
编辑
所以这里有一些代码,我已经设法将问题缩小到特定的代码路径。
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"
}
此代码路径抛出我在上面附加的异常 (objc_release)。
我注意到两件重要的事情:
1) 如果我在提取后插入 [moc reset]
,则不再引发异常(这当然不能扩展我的程序,因为我正在处理 NSFetchRequestControllers 等)。
2) 如果我不使用主对象上下文,而是使用私有队列中的对象上下文,那么也不会引发异常。
完整回溯:
(lldb) 线程回溯
- 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 CoreFoundationCFRunLoopRunSpecific + 443 frame #9: 0x041899fb CoreFoundation
CFRunLoopRunInMode + 123 frame #10: 0x05c4d24f GraphicsServicesGSEventRunModal + 192 frame #11: 0x05c4d08c GraphicsServices
GSEventRun + 104 frame #12: 0x01de48b6 UIKitUIApplicationMain + 1526 frame #13: 0x000611cd Contacit
main(argc=1, argv=0xbfff83b0) + 141 at main.m:16 frame #14: 0x0482cac9 libdyld.dylib`start + 1
非常感谢调查中的任何帮助!
显然这是问题的原因...在我的扩展 NSManagedObject class 中我重写了这个方法
- (void)willTurnIntoFault
{
[super willTurnIntoFault];
if ([self observationInfo])
{
NSLog(@"%@ has observers:\n%@", [self objectID], [self observationInfo]);
}
}
删除这个问题解决了这个问题。