Пример кода Objective-C, который преднамеренно сообщает освобожденный объект
Я новичок в Objective -C и XCode, и приложение, которое я сейчас пишу, получает печально известную EXC_BAD_ACCESS
ошибка.
Почти все рекомендуют начинать решать проблему с помощью NSZombies. Я думаю, что у меня работает NSZombies, но xcode не дает мне предупреждения о том, что зомби были отправлены сообщения, когда мое приложение зависало.
Прежде чем я продолжу свою отладку, я хотел бы запустить некоторый код, который наверняка приведет к отправке сообщения зомби (выделенный объект).
Что такое простой фрагмент кода, где сообщение отправляется на освобожденный объект, что вызывает сценарий, когда NSZombies должен предупредить меня?
2 ответа
Для не ARC-кода:
- (IBAction) messageZombie:(id)sender {
id a = [[NSObject alloc]init];
[a release];
NSLog(@"%@", [a description]);
}
Это даст вам EXC_BAD_ACCESS с отключенными зомби и сообщением "сообщение отправлено освобожденному экземпляру" с включенными зомби.
Если ваш проект использует ARC, то немного сложнее надежно вызвать сообщения для выделенных объектов (в конце концов, это и есть точка ARC).
Это работает:
- (IBAction) messageZombie:(id)sender {
id a = [[NSObject alloc]init];
id __unsafe_unretained b =a;
a=nil;
NSLog(@"%@", [b description]);
}
Это, вероятно, не очень похоже на то, что делает ваш настоящий код, потому что, черт возьми, кто использует __unsafe_unretained, в любом случае? Но если вы просто хотите убедиться, что NSZombies включены правильно, это должен быть разумный контрольный пример.
Если вы ищете в своем коде подозрительные места, то наверняка поищите указатели __unsafe_unretained, хотя вы не найдете никаких *, и дважды проверьте, что правильные приведения используются для объектов CoreFoundation, которые приводятся к объектам Какао.
* Если ваш проект должен поддерживать версии OS X до 10.7 или версии iOS более ранние, чем 5.0, то вы не можете использовать __weak указатели, поэтому в таком проекте вы можете ожидать, что __unsafe_unretained используется чаще.
Вы можете создать объект CF, связать его с объектом Objective-C, затем освободить его и попытаться использовать соединенный мостом объект. Я думаю, что вы должны использовать __bridge
чтобы заставить себя вести себя так, как ты хочешь.