Освобождение ссылок на базовые объекты - PullRequest
20 голосов
/ 15 мая 2009

Нужно ли освобождать объекты Core Foundation для очистки памяти? И если да, то как?

Например, в коде:

ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef peopleArray = ABAddressBookCopyArrayOfAllPeople(addressBook);

мне нужно выпустить peopleArray? А как насчет addressBook?

Ответы [ 5 ]

26 голосов
/ 15 мая 2009

Правила для управления памятью в Core Foundation аналогичны правилам в Какао: если метод, который возвращает ссылку, содержит слова «создать» или «копировать», вы являетесь владельцем ссылки и должны вызвать CFRelease() на эту ссылку, чтобы отказаться от права собственности. В противном случае вы не владеете ссылкой и должны позвонить CFRetain, чтобы стать владельцем (обязательно требуя последующего CFRelease для отказа от этого нового владельца). Эти правила, взятые из Руководства по программированию управления памятью для Core Foundation:

  • Если вы создаете объект (либо непосредственно или сделав копию другой объект - см. «Создание Правило »), оно принадлежит вам.
  • Если вы получите объект из другого места, вы делаете не владею им. Если вы хотите предотвратить это будучи утилизированным, вы должны добавить себя как владельца (используя CFRetain).
  • Если вы являетесь владельцем объект, вы должны отказаться от права собственности когда вы закончили использовать его (с использованием CFRelease).

В вашем примере должны быть освобождены как addressBook, так и peopleArray. Поскольку в Core Foundation нет эквивалента autorelease, если вы возвращаете ссылку из метода, верните массив без его освобождения. Вы должны (если вы не злы), затем включить «создать» в имя метода, чтобы указать вызывающей стороне, что теперь они владеют ссылкой на возвращенный объект. В этом случае CFArray предоставляется по бесплатному мосту NSCFArray, объекту Objective-C, который наследуется от NSObject. Таким образом, вы можете привести peopleArray к NSArray* и autorelease, что, если вам нужно вернуть его из функции / метода:

return [(NSArray*)peopleArray autorelease];

Обратите внимание, что это работает только для бесплатных мостовых классов. Насколько я понимаю, довольно сложно создать собственные бесплатные мостовые классы, и только примитивные (строковые, массивные и т. Д.) Классы CF являются бесплатными мостовыми, поэтому этот подход не всегда будет работать. Наконец, если вы можете избежать использования autorelease (то есть вы можете сделать управление памятью более четким), это, вероятно, всегда хорошо.

26 голосов
/ 15 мая 2009

Да, в CoreFoundation вы должны выпустить что-нибудь с именем Create или Copy. Вы делаете это с CFRelease (). В вашем случае вы должны освободить ссылки на массив и адресную книгу.

4 голосов
/ 15 мая 2009

Еще один маленький момент, который еще никто не упомянул, некоторые классы CF имеют "бесплатный телефонный мост" со своим NS-аналогом. CFString и NSString, CFArray и NSArray оба являются примерами. Это актуально, так как вы можете просто использовать release с этими классами.

См. Этот другой вопрос StackOverflow для получения дополнительной информации.

3 голосов
/ 06 мая 2012

Для ARC вы можете использовать.

return (__bridge_transfer NSArray*)peopleArray;

"__ bridge_transfer" передаст право собственности на ARC, и, следовательно, вам не нужно больше вызывать релиз.

3 голосов
/ 15 мая 2009

Я бы предложил прочитать руководство Apple по управлению памятью Core Foundation для более подробного обсуждения этого вопроса. У них есть аналогичное руководство для общего управления памятью Какао.

Чтобы освободить объект CF, вы должны вызвать функцию CFRelease.

...