Пример кода Objective-c, который намеренно сообщает об освобожденном объекте

Я новичок в objective-c и xcode, и приложение, которое я сейчас пишу, выдает печально известную ошибку EXC_BAD_ACCESS.

Практически все рекомендуют начинать решать проблему с помощью NSZombies. Я думаю, что у меня работает NSZombies, но xcode не сообщает мне о том, что зомби получает сообщение, когда мое приложение аварийно завершает работу.

Прежде чем я продолжу отладку, я хотел бы запустить некоторый код, который обязательно должен привести к отправке сообщения зомби (объект с освобожденным выделением).

Что представляет собой простой фрагмент кода, в котором сообщение отправляется освобожденному объекту, вызывая сценарий, в котором NSZombies должен предупредить меня?


person Alex Crist    schedule 14.08.2015    source источник
comment
@zaph Нет, это утечка памяти. Зомби - это указатель на освобожденный объект.   -  person rmaddy    schedule 14.08.2015
comment
@zaph Если у вас включены зомби, зомби - это то, что остается, когда вы освобождаете объект. Вместо того, чтобы освобождать эту память, зомби удерживает эту память и может предупредить вас, когда ему будет отправлено сообщение - что должно быть освобожденным объектом.   -  person Alex Crist    schedule 14.08.2015
comment
@zaph Вся суть зомби (как инструмента отладки) состоит в том, чтобы найти случаи, когда у вас все еще есть указатель на объект, который был освобожден, а затем вы пытаетесь получить доступ к объекту.   -  person rmaddy    schedule 14.08.2015
comment
@zaph, этот вопрос конкретно касается NSZombie, о чем вы говорите?   -  person Mark Bessey    schedule 14.08.2015
comment
Хорошо, я придерживаюсь распространенного мнения, что зомби не может существовать без включения объектов зомби. Это скорее противоречит концепции зомби-задачи, номенклатура которой, как я полагаю, предшествует зомби-объектам.   -  person zaph    schedule 14.08.2015


Ответы (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_unrehibited? Но если вы просто хотите убедиться, что у вас правильно включен NSZombies, это должно быть разумным тестом.

Если вы ищете подозрительные места в своем коде, то обязательно поищите указатели __unsafe_unreolated, хотя вы не найдете никаких *, и дважды проверьте, используются ли правильные приведения для объектов CoreFoundation, которые приводятся к объектам Какао.

* Если ваш проект должен поддерживать версии OS X до 10.7 или версии iOS до 5.0, тогда вы не можете использовать __weak указатели, поэтому в проектах такого типа вы ожидаете, что __unsafe_unretended используется чаще.

person Mark Bessey    schedule 14.08.2015
comment
@MarkBessey Спасибо, это то, что я ищу, единственная проблема в том, что у меня включен автоматический подсчет ссылок, и я получаю сообщение об ошибке: ARC запрещает явную отправку сообщения о выпуске - person Alex Crist; 14.08.2015
comment
Это может не привести к сбою, даже если зомби отключены. - person rmaddy; 14.08.2015
comment
Что ж, если у вас включен ARC, у вас не должно быть зомби, если вы не используете слабые указатели неправильно. Достаточно честно - я сделаю еще один пример для кода ARC. - person Mark Bessey; 14.08.2015
comment
@MarkBessey Возможно неправильное использование слабого указателя, я вхожу в проект, в котором проблема была до того, как я начал. Я ценю помощь. - person Alex Crist; 14.08.2015
comment
Также не упоминается, что опция Enable Zombie Objects должна быть включена. Также следует отметить, что с этим параметром каждое освобождение памяти будет протекать, так как память не будет освобождена, важно удалить этот параметр, когда вы закончите. - person zaph; 14.08.2015
comment
@zaph Совершенно верно, у меня включен параметр «Включить зомби-объекты», и я обязательно отключу его, когда закончу отладку, чтобы предотвратить присущие им утечки памяти. - person Alex Crist; 14.08.2015
comment
@MarkBessey Отличный ответ и хороший намек на unsafe_unreolated - на самом деле в проекте шокирующе широко используются указатели unsafe_unreolated. - person Alex Crist; 14.08.2015
comment
Я должен был это квалифицировать. В старых версиях iOS не было поддержки __weak, поэтому вы застряли с __unsafe_rehibited. Если вам не нужно поддерживать версии iOS до 5.0, замена всех их на __weak может быть действительно хорошей идеей. - person Mark Bessey; 14.08.2015
comment
@rmaddy по своей природе вещей вы не можете гарантировать, что конкретная последовательность шагов гарантирует, что объект находится в недопустимом состоянии. Я мог бы попытаться сделать этот код более ненадежным, но они действительно работали, когда я их тестировал. - person Mark Bessey; 15.08.2015

Вы можете создать объект CF, связать его с объектом Objective-C, затем отпустить и попытаться использовать объект с мостом. Я думаю, вам нужно использовать __bridge, чтобы заставить его вести себя так, как вы хотите.

person Tim Johnsen    schedule 18.08.2015