Что вы думаете об этом коде в Objective-C, который выполняет итерацию через retain count и вызывает release каждую итерацию? - PullRequest
8 голосов
/ 16 декабря 2011

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

-(void)releaseMySelf{
    for (int i=myRetainCount; i>1; i--) {
        [self release];
    }
    [self autorelease];
}

Насколько мне известно, в модели управления памятью Objective-C первое правило состоит в том, что объект, который выделяет другой объект, также отвечает за его освобождение в будущем.Вот почему я не понимаю смысл этого кода.Есть ли смысл?

Ответы [ 4 ]

17 голосов
/ 16 декабря 2011

Автор пытается обойти, не разбираясь в управлении памятью. Он предполагает, что у объекта есть счет сохранения, который увеличивается с каждым хранением, и поэтому пытается уменьшить его, вызывая это количество выпусков. Вероятно, он не реализовал «также несет ответственность за его выпуск в будущем». часть вашего понимания.

Однако см. Много ответов здесь, например. здесь и здесь и здесь .

Read Концепции управления памятью Apple .

Первая ссылка содержит цитату из Apple

Метод retainCount не учитывает ожидающий авто-релиз сообщения, отправленные получателю.

Важно: Этот метод обычно не имеет значения в отладочной памяти вопросы управления . Потому что любое количество объектов каркаса может иметь сохранил объект для хранения ссылок на него, в то время как на В то же время пулы авто-релиза могут содержать любое количество отложенных релизы на объекте, очень маловероятно, что вы можете получить полезные информация из этого метода . Чтобы понять основные правила Управление памятью, которое вы должны соблюдать, прочитайте «Управление памятью» Правила». Для диагностики проблем управления памятью используйте подходящий инструмент: Статический анализатор LLVM / Clang обычно может найти управление памятью проблемы даже до запуска вашей программы. Инструмент Object Alloc в приложении Инструменты (см. Руководство пользователя инструментов) можно отслеживать размещение и уничтожение объектов. Акула (см. Руководство пользователя Акулы) также профили распределения памяти (среди множества других аспектов вашего программа).

7 голосов
/ 16 декабря 2011

Поскольку все ответы, по-видимому, неправильно интерпретируют myRetainCount как [self retainCount], позвольте мне предложить причину, по которой этот код мог быть написан: возможно, этот код каким-то образом порождает потоки или иным образом заставляет клиентов регистрироваться в нем, и что myRetainCountфактически число этих клиентов хранится отдельно от фактического количества сохраняемых ОС.Однако каждый из клиентов может также получить свое собственное сохранение в стиле ObjC.

Так что эта функция может быть вызвана в случае, когда запрос отменен, и может просто уничтожить всех клиентов одновременно, изатем выполните все выпуски.Это не очень хороший дизайн, но если так работает код (и вы не пропустили int myRetainCount = [self retainCount] или переопределения retain / release), по крайней мере, это не обязательно ошибка.

Это, однако, очень вероятно, плохое распределение обязанностей или грязная и избитая попытка избежать удержания кругов без реального улучшения.

3 голосов
/ 16 декабря 2011

Это грязный хак для принудительного освобождения памяти: если остальная часть вашей программы написана правильно, вам никогда не нужно делать ничего подобного. Как правило, ваши удержания и выпуски находятся в балансе, поэтому вам никогда не нужно смотреть на количество удержаний. Этот фрагмент кода говорит: «Я не знаю, кто сохранил меня и забыл освободить, я просто хочу, чтобы моя память освободилась; мне все равно, что ссылки на другие будут болтаться с этого момента». Это не собирается скомпилировать с ARC (как ни странно, переключение на ARC может просто исправить ошибку, которую автор пытался обойти).

2 голосов
/ 16 декабря 2011

Смысл кода заключается в том, чтобы заставить объект освободиться прямо сейчас, независимо от того, какими могут быть будущие последствия.(И это будет иметь последствия!)

Код фатально ошибочен, потому что он не учитывает тот факт, что кто-то на самом деле «владеет» этим объектом.Другими словами, что-то «выделило» этот объект и любое количество других вещей, возможно, «сохранило» этот объект (возможно, структура данных, такая как NSArray, может быть пул автоматического выпуска, может быть, некоторый код на стековом кадре, который просто «сохраняет»);все эти вещи имеют право собственности на этот объект.Если объект совершает самоубийство (что и делает releaseMySelf), эти «владельцы» внезапно указывают на плохую память, и это приведет к неожиданному поведению.

Надеюсь, код, написанный таким образом, просто потерпит крах.Возможно, первоначальный автор избежал этих сбоев, потеряв память в другом месте.

...