Сохранить счет и скопировать в сеттер? - PullRequest
1 голос
/ 01 октября 2009

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

код

// IMPLEMENT
@implementation CelestialBody
- (void)setName:(NSString *)newName{
    if(name != newName) {
        [name release];
        name = [newName copy];
    }
}
- (void)dealloc{
    [name release];
    name = nil;
    [super dealloc];
}
@end

.

// ------------------------------------------------------------------- **
// MAIN: 30th September 2009
// ------------------------------------------------------------------- **

#import <Foundation/Foundation.h>
#import "CelestialBody.h"

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    CelestialBody *newPlanet = [[CelestialBody alloc] init];
    NSString *myString = [[NSString alloc]initWithFormat:@"go home"];
    NSLog(@"RetainCount_1: %d",[myString retainCount]);

    [newPlanet setName: myString];
    NSLog(@"RetainCount_2: Incremented by copy in setName");    

    // Clean up
    NSLog(@"RetainCount_2: %d -Before Release",[myString retainCount]);
    [newPlanet release];
    [myString release];
    [pool drain];
    NSLog(@"RetainCount_1: %d -After Release",[myString retainCount]);
    return 0;
}
// ------------------------------------------------------------------- **

OUTPUT

Running…
2009-10-01 09:28:50.395 RetainCount_1: 1
2009-10-01 09:28:50.399 RetainCount_2: Incremented by copy in setName
2009-10-01 09:28:50.399 RetainCount_2: 2 -Before Release
2009-10-01 09:28:50.400 RetainCount_1: 1 -After Release
Debugger stopped.

В настоящее время я перечитываю Руководство по управлению памятью, чтобы попытаться увидеть, что я пропустил.

большое спасибо

EDIT

Только что добавил релиз в dealloc. Похоже, это было то, чего мне не хватало.

- (void)dealloc{
    [name release];
    name = nil;
    [super dealloc];
}

1021 * Гэри *

Ответы [ 3 ]

3 голосов
/ 01 октября 2009

- переменная myString, которая будет освобождена.

[myString release];

Все знаки указывают на да.

Не похоже, что с выхода?

NSLog(@"RetainCount_2: %d",[myString retainCount]);
[myString release];

Вывод вашего оператора NSLog не отражает сообщение release, поскольку сообщение release еще не произошло.

Кроме того, не беспокойтесь о сохранении счета. Они могут быть очень обманчивы. Пока вы следуете правилам Какао и не создаете никаких циклов владения (А владеет Б, владеет С, владеет А), у вас редко будут проблемы.

2 голосов
/ 01 октября 2009

Это, по сути, не ответ на ваш вопрос, а объяснение того, что вы видите: последний вызов retainCount отправляется на освобожденный объект, что является неопределенным поведением. Оказывается, объект еще не был перезаписан, так что он все еще работает, в том смысле, что диспетчер методов все еще может видеть старые данные и не осознает, что они недействительны. Вы никогда не получите 0 от вызова retainCount, потому что такой объект не может существовать.

1 голос
/ 01 октября 2009

Я думаю, [newName copy] на самом деле не копирует NSString, потому что NSString является неизменным? Я никогда не думал об этом, но для меня это имеет смысл.

В конце вашей программы вы выпускаете newPlanet и myString. Мой вопрос, вы выпускаете имя переменной экземпляра в методе -dealloc CelestialBody? Если нет, то я полагаю, что у вас утечка памяти.

  1. Создать myString: retainCount NSString равен 1
  2. [newPlanet setName:]: retainCount строки NSString равен 2
  3. [выпуск newPlanet]: retainCount NSString равен 2? Я предполагаю, что вы не выпускаете это в -dealloc.
  4. [myString release]: retainCount NSString равен 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...