Утечка памяти с NSString - PullRequest
0 голосов
/ 07 июля 2011

Я прочитал почти каждый Вопрос здесь о SO, касающийся управления памятью, в котором используются строки NSStrings, но я не могу решить эту проблему.

@ интерфейс:

@property (nonatomic, retain) NSString *criticalTranscription;

@ реализация: viewDidLoad:

criticalTranscription = [[NSString alloc] init];

NSArray *paragraphs = [doc valueForKeyPath:@"critical.text"];
for(int i = 0; i < [paragraphs count]; i++) 
{
    criticalTranscription = [criticalTranscription stringByAppendingString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]];
    criticalTranscription = [criticalTranscription stringByAppendingString:@"\n\n"];
}
[transcription setText:criticalTranscription];

@ XIB UISegmentedControl с IBAction, связанным с:

- (IBAction) changeText:(id)sender
{
  if(transcriptionSelector.selectedSegmentIndex == 1)
    [transcription setText:diplomaticTranscription];
  else
    [transcription setText:criticalTranscription];
}

Когда я изменяю значение UISegmentControl (первым делом сразу после загрузки, больше ничего не запускается), я сталкиваюсь с этой ошибкой (NSZombieEnabled = YES):

2011-07-07 01:10:43.639 Transcribe[404:707] *** -[CFString length]: message sent to deallocated instance 0x1189300

Я не вижу ничего существенного в следе. Без NSZombieEnabled критическая транскрипция просто указывает на случайные массивы или что-то еще. Дальнейшее использование переменной или каких-либо выпусков невозможно.

Я провел анализ без каких-либо подозрительных утечек.

В чем проблема?

Ответы [ 3 ]

3 голосов
/ 07 июля 2011

Проблема в том, что вы перезаписываете ссылку на вашу строку другой, которой вы не владеете.

// you own the empty string returned here
criticalTranscription = [[NSString alloc] init]; 

NSArray *paragraphs = [doc valueForKeyPath:@"critical.text"];
for(int i = 0; i < [paragraphs count]; i++) 
{
    // immediately overwrite allocated instance (that you own)
    criticalTranscription = [criticalTranscription stringByAppendingString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]];
    criticalTranscription = [criticalTranscription stringByAppendingString:@"\n\n"];
}

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

Кроме того, чтобы использовать встроенную функцию управления памятью, необходимо использовать self.criticalTranscription, а не просто criticalTranscription. Без self. вы используете переменную экземпляра напрямую.

1 голос
/ 07 июля 2011

Две проблемы:

  • Вы пропускаете первый экземпляр строки
  • Каждое последующее присваиваемое ему значение автоматически высвобождается

Чтобы исправить это, самый простой способ - изменить criticalTranscription на NSMutableString. Тогда вы можете сделать:

criticalTranscription = [[NSMutableString alloc] init];

NSArray *paragraphs = [doc valueForKeyPath:@"critical.text"];
for(int i = 0; i < [paragraphs count]; i++) 
{
    [criticalTranscription appendString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]];
    [criticalTranscription appendString:@"\n\n"];
}
[transcription setText:criticalTranscription];

... альтернативно,

[criticalTranscription appendFormat:@"%@\n\n", [[paragraphs objectAtIndex:i] valueForKey:@"p"]];

Также обратите внимание, что вам нужно позвонить release на criticalTranscription, как только вы закончите, либо в конце вашего -viewDidLoad, либо в соответствующем -viewDidUnload.

1 голос
/ 07 июля 2011

В вашем цикле for

criticalTranscription = [criticalTranscription stringByAppendingString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]];
criticalTranscription = [criticalTranscription stringByAppendingString:@"\n\n"];

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

Вы можете сохранить его или использоватьсвойство с @property(nonatomic, copy)NSString *criticalTranscription; и использовать свойство, а не ivar.

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