Leak или Crash - разница между авто-выпуском и выпуском - PullRequest
2 голосов
/ 27 декабря 2010

У меня вопрос к пониманию. Этот метод дан:

- (NSArray*)test {
 NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://stackoverflow.com/"]];
 NSString *result = [[NSString alloc] initWithBytes:[data bytes] 
            length:[data length] 
             encoding:NSMacOSRomanStringEncoding];
 result = [result stringByAppendingString:@"something"];
 NSArray *arr = [NSArray arrayWithObject:result];
 //[result release];
 return arr;
}

Если я раскомментирую release, приложение рухнет и скажет, что не может получить доступ к освобожденному объекту.
Не release строковое значение result Instruments сообщит об утечке (NSPlaceholderString).

Я могу autorelease в той же строке, что и я alloc, это решит проблему (что я сейчас делаю в своем приложении).

Если я правильно понимаю, stringByAppendingString: должен создать объект с автоматическим выпуском, чтобы можно было освободить «старый» результат. Тогда метод arrayWithObject: должен copy объект в массив. Поэтому я думал выпустить строку после ее копирования в массив.

Я что-то упускаю или что-то не так с моими знаниями?

Ответы [ 2 ]

11 голосов
/ 27 декабря 2010

Давайте пройдемся по вашему коду построчно.

- (NSArray*)test {
 NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://stackoverflow.com/"]];

Это создает объект данных. Вы не владеете им, но он останется на все остальное время метода. Пока все хорошо.

 NSString *result = [[NSString alloc] initWithBytes:[data bytes] 
                                             length:[data length] 
                                           encoding:NSMacOSRomanStringEncoding];

Это создает строковый объект, которым вы владеете. Опять же, здесь нет проблем - нам просто нужно выпустить его позже.

result = [result stringByAppendingString:@"something"];

Вы отбрасываете свою ссылку на строковый объект, который был в result, и сохраняете новый строковый объект, который вам не принадлежит. Это утечка, потому что вы больше не можете освободить исходную строку. Кроме того, вы правильно заметили, что новая строка может рассматриваться как объект с автоматическим освобождением, что означает, что вы не должны освобождать ее.

NSArray *arr = [NSArray arrayWithObject:result];

Вопреки вашему убеждению, это ничего не копирует. Он просто сохраняет ссылку на новую строку и сохраняет ее.

//[result release];

Вы не должны выпускать result на этом этапе, потому что объект, который он содержит, не принадлежит вам - вы получили его от stringByAppendingString:, а не от метода с new, alloc, retain или copy в его названии. Освобождение этого объекта, которым вы не владеете, почти наверняка приведет к падению в какой-то момент. Старый объект, которым вы владеете и должен выпустить , был потерян двумя строками ранее, и освобождение чего-то другого на его месте не поможет.

8 голосов
/ 27 декабря 2010
result = [result stringByAppendingString:@"something"];

Эта строка заменяет первую выделенную строку новой автоматически выпущенной строкой.

Таким образом, первая строка просочилась, а вторая не должна быть освобождена.Это объясняет, почему раскомментированная строка аварийно завершает работу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...