Более конкретное, общее управление памятью Objective-C - PullRequest
2 голосов
/ 23 октября 2009

Все, что я читал об управлении памятью target-c, делает его невероятно простым. Перефразируя каждого: «освободить то, что вы выделяете, сохраняете или копируете». Но я думаю, что есть некоторые более конкретные случаи, которые не так очевидны. Ниже приведены примеры ситуаций. Какова правильная процедура для каждого:

СИТУАЦИЯ № 1:

Foo *foo = [[foo alloc] init];
Foo *fooToo = [[[foo alloc] init] autorelease];

foo = fooToo;

нужно ли освобождать foo, прежде чем он будет назначен на fooToo?

СИТУАЦИЯ № 2 Я, кажется, получаю много сбоев, когда я делаю такие вещи, как: (.h и .m смешаны для удобства)

Foo *foo;
@property (nonatomic, retain) Foo *foo;
@synthesize foo;

-(id)init{
self = [super init];
}

-(void)dealloc{
[super dealloc];
[foo release];
}

Мне постоянно говорят "всегда указывайте в dealloc то, для чего вы устанавливаете свойство retain". Но это рухнет, если все будет сделано, как я показал.

СИТУАЦИЯ № 3 Аналогичная ситуация, которая также приведет к сбою: (.h и .m смешаны для удобства)

Foo *foo;
@property (nonatomic, retain) Foo *foo;
@synthesize foo;

-(id)init{
self = [super init];
self.foo = nil;
}

-(void)dealloc{
[super dealloc];
[foo release];
}

по какой-то причине, когда мой код сводится к dealloc, foo не == ноль.

СИТУАЦИЯ № 4 И наконец, просто вопрос: какой общий мыслительный процесс используют люди при выборе между

 self.foo = bar;

и

 foo = bar;

когда foo объявляется так же, как в приведенных выше случаях? self.foo - это просто еще один способ кодирования:

foo = [bar retain];

Ответы [ 2 ]

6 голосов
/ 23 октября 2009

Ситуация № 1:

Да, вам нужно выпустить foo, прежде чем вы потеряете ссылку на него. Учитывая, что вы выделили его, вы несете ответственность за его освобождение. Если вы повторно назначите foo перед его освобождением, вы больше не сможете его разблокировать!

Ситуация № 2:

Правильная реализация dealloc:

- (void)dealloc {
    [foo release];
    [super dealloc];
}

Метод dealloc должен вызывать метод супер dealloc, а не метод release. Кроме того, вам нужно освободить поля перед вызовом [super dealloc]

Ситуация № 3: То же, что и ситуация № 2.

Ситуация № 4:

Я всегда предпочитаю использовать self.foo = bar, так как при необходимости он автоматически выполняет следующие шаги:

  1. выпуск foo
  2. сохраняя bar
  3. присвоение foo bar

Назначения foo = bar и foo = [bar retain] не освобождают предыдущий объект foo.

4 голосов
/ 23 октября 2009

Подождите. Стоп. Ответ Msaeed является правильным, построчно, но не в состоянии подчеркнуть реальную проблему.

Вы либо не мыслите как компьютер, либо вы принимаете слишком много магии на строку кода.

Пожалуйста, не воспринимайте это как оскорбление - это очень простая ошибка, которую допускает почти каждый программист, когда только знакомится с окружением (я сделал несколько действительно фантастических магических предположений, когда начинал с Objective-C в 1989).

Давайте пересмотрим ситуации.

СИТУАЦИЯ № 1: ... удалить ненужный код ...

foo = fooToo;

Это простое задание. Все, что foo содержалось до этого - ссылка на объект в вашем случае - теперь будет перезаписано значением fooToo. Там нет магии. Не требуется выполнение дополнительных методов или строк кода.

Если foo содержит ссылку на сохраненный объект, pior этой строки кода. Ссылка будет перезаписана. Если вам нужно release foo перед перезаписью ссылки, сделайте это, но это ортогонально назначению.

СИТУАЦИЯ № 2: ... удалить ненужный код ...

-(void)dealloc{ [super dealloc]; [foo release]; }

Играй в компьютер; вы запрашиваете super для dealloc, а затем предполагаете, что переменная экземпляра действительна после освобождения super. Плохие новости. Boom.

Здесь нет магии. foo является ссылкой от до self на переменную экземпляра. -dealloc уничтожает себя и, таким образом, foo больше не действует.

(Я полагаю, статический анализатор поймает это. Если нет, то должен.)

СИТУАЦИЯ № 3:

См. № 2. Это точно такая же проблема. Вы получаете доступ к переменной экземпляра экземпляра, который больше не является допустимым.

СИТУАЦИЯ № 4:

self.foo = bar;

Точно так же, как:

`[self setFoo: bar];

(кроме любого сеттера = махинации)

Таким образом, ключевое отличие заключается в том, что делает реализация - рукописная или @synthesized - из -setFoo :. В твоем случае это retain с бар. Что отличается от foo = bar; тем, что никакого сохранения не происходит; это просто присвоение ссылки на bar.

Я настоятельно рекомендую вам вернуться к вводной документации Objective-C. Это поможет Тем не менее, я также призываю вас сделать шаг назад и по-настоящему продумать, что именно делает каждая строка кода в вышеуказанных ситуациях. В этом нет магии, и фактическое поведение очень простое.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...