У вас есть «потенциальная утечка», потому что Анализатор видит, что вы выделили память для экземпляра DoublyLinkedList
(используя new
), поместили его в локальную переменную с именем dll
и не освободили эту память в тот же объем.
Предполагая, что заданный вами элемент doublyLinkedList
также является свойством, объявленным как retain
ing, у вас также есть фактическая утечка, потому что вы чрезмерно сохранили DoublyLinkedList
что вы создаете здесь.
Правила владения говорят, что у вас есть одна претензия к этому экземпляру, потому что вы вызвали new
для его создания. Когда вы передаете экземпляр в setDoublyLinkedList:
, он сохраняется, и у вас есть две претензии. Когда метод init
заканчивается, у вас есть только одна ссылка на экземпляр через свойство ivar / - вы потеряли локальную переменную - это означает, что у вас больше заявок на владение, чем у вас есть ссылки. Это хороший признак того, что у вас будет утечка.
Чтобы устранить утечку, вам необходимо отказаться от одной из ваших претензий до окончания init
метода. Это можно сделать одним из двух способов, используя release
, как только свойство будет установлено:
DoublyLinkedList * dll = [DoublyLinkedList new];
[self setDoublyLinkedList:dll];
[dll release];
или autorelease
:
[self setDoublyLinkedList:[[DoublyLinkedList new] autorelease]];
// Or equivalent procedures involving a temp variable
Тем не менее, следует отметить, что использование сеттеров в init
может быть проблематичным (см. Также рецензия Майка Эша на тему ), поскольку средства доступа могут - потенциально - есть побочные эффекты, которые зависят от того, что ваш объект уже полностью настроен. Похоже, что есть два лагеря по этой проблеме, и, вероятно, лучше прочитать об этом и прийти к своим собственным выводам, но вы можете обнаружить, что это упрощает ваши методы инициализатора для назначения ivars вместо использования свойств:
if( self ){
doublyLinkedList = [DoublyLinkedList new];
}
Это абсолютно правильно с точки зрения управления памятью.
Наконец, если DoublyLinkedList
- это класс, код которого у вас есть, вы можете также написать вспомогательный конструктор, который вернет вам новый, автоматически выпущенный экземпляр. Соглашение в Какао состоит в том, чтобы просто назвать метод после класса со стандартным регистром имени метода, например так:
+ (id) doublyLinkedList {
return [[[self alloc] init] autorelease];
}
Обратите внимание, что это метод класса:
if( self ){
[self setDoublyLinkedList:[DoublyLinkedList doublyLinkedList]];
}
и см. мой ответ на "Самораспределяющиеся объекты" для объяснения этих конструкторов.