Можете ли вы просто проверить, присваивается ли ссылке на объект значение nil
, чтобы указать, что оно было освобождено?
Нет, потому что отправка release
сообщения объекту и присвоение nil
переменной - это две разные и не связанные вещи.
Самое близкое, что вы можете получить, это то, что присвоение чего-либо для свойства strong / удержания или копирования, которое преобразуется в сообщение доступа, приводит к освобождению предыдущего значения свойства (которое выполняется установщиком). Тем не менее, наблюдение за значением свойства - скажем, с помощью KVO - не означает, что вы будете знать, когда объект будет освобожден; особенно, когда освобождающий объект освобождается, вы не получите уведомление, когда оно отправит release
непосредственно в принадлежащий объект. Вы также получите предупреждающее сообщение в вашей консоли (потому что владелец объекта умер, когда вы его наблюдали), и вы не хотите шумных предупреждающих сообщений от юнит-теста. Кроме того, вы должны были бы специально наблюдать каждое свойство каждого объекта , чтобы проверить это - пропустите одно, и вы можете пропустить ошибку.
Сообщение release
для объекта не влияет на переменные, которые указывают на этот объект. Ни один не делает освобождение.
Это немного меняется при ARC : переменные со слабой ссылкой будут автоматически назначаться nil
, когда указанный объект исчезнет. Это не очень вам поможет, поскольку переменные strong по определению не помогут: если существует сильная ссылка на объект, объект не будет (хорошо , не должен ) уходить, потому что сильная ссылка будет (должна) поддерживать его. Объект, умирающий раньше, чем должен, - это одна из проблем, которую вы ищете, а не то, что вы хотите использовать в качестве инструмента.
Вы теоретически можете создать слабую ссылку на каждый объект, который вы создаете, но вам придется обращаться к каждому объекту отдельно, создавая переменную для него вручную в своем коде. Как вы можете себе представить, огромная боль и наверняка пропустить объекты.
Кроме того, какие у вас есть гарантии относительно времени, в которое объекты фактически освобождаются?
Объект освобождается путем отправки ему сообщения release
, поэтому объект освобождается при получении этого сообщения.
Возможно, вы имели в виду «освобожден». Выпуск просто приближает его к этой точке; объект может быть выпущен много раз, и у него все еще будет долгая жизнь, если каждый релиз просто уравновешивает предыдущее удержание.
Объект освобождается, когда его отпускают в последний раз. Это происходит немедленно. Печально известный retainCount
даже не падает до 0, как выяснили многие умные люди, пытавшиеся написать while ([obj retainCount] > 0) [obj release];
.
На самом деле может быть два ответа: один использует пул автоматического выпуска, а другой - нет.
Решение, использующее пул автоматического выпуска, работает только для объектов, которые были автоматически освобождены; по определению объекты, которые не были автоматически освобождены, не попадают в пул. Вполне допустимо, а иногда и желательно, никогда не высвобождать некоторые объекты автоматически (особенно те, которые вы создали много тысяч). Более того, вы не можете заглянуть в бассейн, чтобы увидеть, что в нем, а что нет, или попытаться ткнуть каждый объект, чтобы увидеть, мертв ли он.
Как бы вы написали модульный тест - например, с использованием OCUnit - чтобы убедиться, что объекты должным образом освобождаются / сохраняются в Cocoa / Objective-C?
Лучшее, что вы можете сделать, это установить NSZombieEnabled
в YES
в setUp
и восстановить его предыдущее значение в tearDown
. Это приведет к перерасходу / недостаточному удержанию, но не к утечкам.
Даже еслиВы могли бы написать модульный тест, который бы тщательно проверял управление памятью, но он все еще был бы несовершенным, потому что он мог бы тестировать только тестируемый код - объекты модели и, возможно, некоторые контроллеры. У вас все еще могут быть утечки и сбои в вашем приложении, вызванные кодом представления, связанными с перьями ссылками и некоторыми параметрами (на ум приходит «Release By Closed») и т. Д.
Вы не можете написать тест вне приложения, который бы гарантировал, что ваше приложение не содержит ошибок в памяти.
Тем не менее, тест, который вы себе представляете, если бы он был автономным и автоматическим, был бы довольно крутым, даже если бы он не мог проверить все. Поэтому я надеюсь, что я не прав и есть способ.