Использование malloc/free в объекте Objective-C

У меня есть класс AudioManager с членом типа AudioBufferList *. (Это структура, объявленная в фреймворке CoreAudio). Поскольку AudioBufferList не является NSObject, я не могу его сохранить, поэтому я должен его выделить/освободить (поправьте меня, если я ошибаюсь).

Мой вопрос в том, где находится «правильное» место, чтобы освободить его? В настоящее время я делаю это в методе dealloc AudioManager. Если я правильно понимаю, этот метод вызывается автоматически, как только сообщение release отправляется экземпляру AudioManager --- это правда? Существует ли какая-либо другая рекомендуемая практика использования alloc/free для не-объектов-членов объектов Objective-C?

Редактировать:

Из документации Apple:

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

Что немного проясняет ситуацию, но ценится больше информации.


person Itamar Katz    schedule 10.01.2011    source источник


Ответы (2)


Да, вам нужно malloc/освободить память. Здесь есть отличный ответ/пример, включая правильное управление памятью:

iPhone: инициализация и выпуск AudioBufferList

Что касается «когда», вы захотите не только освободить память при выпуске AudioManager, но и в случае изменения значения вашего AudioBufferList. Например. Если указатель изначально ссылается на какой-то «экземпляр A» структуры AudioBufferList, а вы изменили его, чтобы он указывал на какой-то «экземпляр B» структуры AudioBufferList, тогда вам нужно освободить память для «экземпляра A», иначе он может быть потерян. (И память будет утечка.)

Один важный момент, и, возможно, тот, который вы знали, но случайно опечатались: dealloc не вызывается, когда release отправляется объекту. Экземпляр NSObject освобождается только тогда, когда его счетчик сохранения достигает нуля. Объект может иметь счетчик удержания 2, а после отправки [myObject release] его счетчик удержания станет 1. Но ему не будет отправлено сообщение dealloc, так как это подразумевает, что какой-то другой объект все еще "владеет" этим экземпляром и полагается на то, что объект остается выделенным и доступным.

person Craig Otis    schedule 10.01.2011
comment
Да, совершенно ясно, что нужно использовать free() перед назначением указателя на другой адрес... Спасибо за пояснение. - person Itamar Katz; 10.01.2011

Вам не нужно делать malloc или бесплатно на нем. Вы должны использовать структуру, такую ​​как CGRect или AudioBufferList, так же, как вы используете int или double. Нет проблем с сохранением, выделением, освобождением, освобождением и т. д. для типов, не являющихся объектами.

Что касается метода dealloc для AudioManager, то он не будет вызываться автоматически при отправке сообщения release, он будет автоматически вызываться, когда счетчик удержания равен 0. Отправка сообщения release объекту уменьшает счетчик удержания на 1. Он все еще может есть другие вещи, которые сохраняют его, и в этом случае он еще не будет освобожден.

Изменить

Пример того, как Apple использует типы структур:

CGRectMake(CGFloat x, CGFloat y, CGFloat width, CGFloat height)
{
  CGRect rect;
  rect.origin.x = x; rect.origin.y = y;
  rect.size.width = width; rect.size.height = height;
  return rect;
}
person GendoIkari    schedule 10.01.2011
comment
Но необъектные типы (такие как AudioBufferList) по-прежнему могут нуждаться в 'c-style' malloc/free, не так ли? Я имею в виду, что иногда вам нужно динамически выделять память. (И спасибо за 2-ю часть вашего комментария). - person Itamar Katz; 10.01.2011
comment
Если нет чего-то особенного в AudioBufferList, что непонятно, то нет. Например, посмотрите на метод Apple, CGRectMake, который я опубликую в редактировании своего ответа. - person GendoIkari; 10.01.2011
comment
Конечно, если вы хотите вернуть только копию своего типа данных. Но что, если вам нужно создать массив из CGRect, размер которого известен только во время выполнения? Тогда, насколько я знаю, вы должны выделять память для него динамически. - person Itamar Katz; 10.01.2011
comment
Почти всегда есть способ избежать фактического использования malloc() и free(), но это не всегда стоит усилий. Например, для массива CGRect можно использовать NSArray из NSValue. - person Steven Fisher; 10.01.2011
comment
Вопрос касается указателя на структуру AudioBufferList, которая будет нулевым указателем для вновь выделенного объекта. Следовательно, malloc и free необходимы для выделения памяти, на которую указывает указатель. - person ughoavgfhw; 10.01.2011