NSZombieEnabled から有益なメッセージなしで EXC_BAD_ACCESS を取得する
-
20-09-2019 - |
質問
私は iPhone 開発の初心者で、数日前に発生した EXC_BAD_ACCESS エラーに苦労しています。私は基本的に Stanford iphone クラスを独立して取得し、NSManagedObjects の配列をそれらを表示するはずの TableViewController に渡そうとしています。アプリケーションはシミュレーターで起動し、tableView にデータを表示しますが、すぐに EXC_BAD_ACCESS でエラーが発生します。
NSZombieEnabled を使用して早期にリリースされたオブジェクトを識別する方法については、ここや他の場所の手順に従いましたが、これは NSZombieEnabled を使用しても役立つメッセージがありません。私の推測では、リリース/自動解放によって解放されなかった未割り当てのメモリにアクセスしようとした何かが原因であるに違いないと思います。そうでなければ、私が修正できた他のエラーと同様に、ゾンビオブジェクトとして認識されていたでしょう。私は C の専門家ではありませんが、インスタンス化せずにオブジェクトを宣言してメッセージを送信すると、そのようなことが起こる可能性があるということでしょうか?コードを調べてそのようなものがないか確認しましたが、結果は空でした。
デバッガーにこのためのスタック トレースがありますが、それをどのように利用するかがわかりません。この問題はアプリの読み込みが完了した後に発生するようで、コード内でブレークポイントを使用して問題をさらに絞り込むことができないため、少しイライラしています。ユーザーとの対話が行われない場合、アプリはアイドル状態のままになるだろうと考えていました。ロードの最後で見えにくいところで失敗しているのか、それともロードが完了した後にバックグラウンドで何かをしているだけなのか。また、これに関するスタックトレースの読み方に関するヒントをいただければ幸いです。
以下にスタックトレースを入力しました(デバッガーからコピーする方法がわかりませんでした)
0 objc_msgSend
1 ??
2 -[NSManagedObject dealloc]
3 -[_PFManagedObjectReferenceQueue _processReferenceQue:]
4 _performRunLoopAction
5 ___CFRunLoopDoObservers
6 CFRunLoopRunSpecific
7 CFRunLoopRunInMode
8 GSEventRunModal
9 GSEventRun
10 UIApplicationMain
11 main
私のプログラムの 2 つの主要なクラスは、最上位のデリゲート クラスと、それが呼び出す ViewTableController です。
`- (void)applicationDidFinishLaunching:(UIApplication *)application {
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
UINavigationController *contactsNavigationController = [[self createContactsNavigationController] retain];
//UINavigationController *recentsNavigationController = [[self createRecentsNavigationController:photos] retain];
tabBarController.viewControllers = [[NSArray alloc] initWithObjects: contactsNavigationController, nil];
[contactsNavigationController release];
//[recentsNavigationController release];
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
}
-(UINavigationController *)createContactsNavigationController {
UINavigationController *contactsNavigationController = [[UINavigationController alloc] init];
UITabBarItem *contactsTabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem: UITabBarSystemItemContacts tag:0];
contactsNavigationController.tabBarItem=contactsTabBarItem ;
[contactsTabBarItem release];
PersonListViewController *personListViewController = [[PersonListViewController alloc] initWithStyle:UITableViewStylePlain];
NSManagedObjectContext *context = [self managedObjectContext];
personListViewController.managedObjectContext=context;
personListViewController.contacts = [self createContacts];
[context release];
personListViewController.title=@"Contacts";
[contactsNavigationController pushViewController:personListViewController animated:false];
return [contactsNavigationController autorelease];
}`
`- (NSArray *)readContacts {
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *filePath = [path stringByAppendingPathComponent:@"FakeData.plist"];
NSArray *plist = [[NSMutableArray arrayWithContentsOfFile:filePath] retain];
return [plist autorelease];
}
- (NSMutableArray *)createContacts {
NSArray * plist = [[self readContacts] retain
NSMutableArray *contactNames = [[NSMutableArray alloc] init];
NSMutableArray *contacts = [[NSMutableArray alloc] init];
for (NSDictionary *photo in plist) {
NSString *contactName = [photo objectForKey:@"user"];
Person *contact = nil;
if (![contactNames containsObject:contactName]) {
contact = (Person *)[NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:managedObjectContext];
contact.name =contactName;
NSError *error;
if (![managedObjectContext save:&error]) {
NSLog(@"SHIT the save person FAILED!!! %@",error);
}
[contacts addObject:contact];
[contactNames addObject:contactName];
} else {
contact = [contacts objectAtIndex:[contactNames indexOfObject:contactName]];
}
[contactName release];
Photo *image = (Photo *)[NSEntityDescription insertNewObjectForEntityForName:@"Photo" inManagedObjectContext:managedObjectContext];
image.imageFile = [photo objectForKey:@"path"];
image.imageName = [photo objectForKey:@"name"];
image.owner = contact;
contact.photos = [NSSet setWithObjects:image,nil];
NSError *error;
if (![managedObjectContext save:&error]) {
NSLog(@"SHIT the save photoFAILED!!! %@",error);
}
[image release];
[contact release];
}
[plist release];
return [contacts autorelease];
}
私のコードが読みにくい場合は、申し訳ありません。
助けてくれてありがとう。
解決
ここにあなたの問題があります:
NSString *contactName = [photo objectForKey:@"user"];
... a bunch of lines later
[contactName release];
objectForKey:
がautoreleased
オブジェクトを返し、あなたはそれを解放するべきではありません。
同様に、insertNewObjectForEntityForName:inManagedObjectContext:managedObjectContext
はautoreleased
オブジェクトを返し、そう[image release]
と[contact release]
を削除
他のヒント
また、NSZombieEnabled がチェックされているにもかかわらず、有益なメッセージなしで EXC_BAD_ACCESS が発生していました。そこで、この経験を共有したいと思います。
シミュレータで数時間格闘した後、デバイスにインストールすることにしました。デバイスでのデバッグから得られたエラー メッセージの方が役に立ちました。
最終的に、EXC_BAD_ACCESS エラーと奇妙な動作が発生していることに気付きました。 名前が変更されました 数個の xibファイル 前日。MainWindow.xib ファイルの「View Controller」オブジェクトを選択し、 NIB 名 財産。その後、すべてがスムーズに進みました。