0

Я использую NSXMLParser для анализа XML-документа. У меня есть следующие функции (среди прочих):Утечка памяти в XML Parser

- (void) parserDidStartDocument:(NSXMLParser *)parser { 

    // Init tempString 
    tempString = [NSMutableString string]; 

}  
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { 

     // save gained data for element "date" 
     if ([elementName isEqualToString:@"date"]) 
      [entryDict setObject:[tempString copy] forKey:kXMLDictDateKey]; 

     [tempString setString:@""]; 
    } 


    // 
    // Character Handling 
    // 
    - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { 
     [tempString appendString:[[XMLParser alloc] stripUnwantedStringChars:string]]; //Just strips tabs and linebreaks and the returns the string 
    } 

tempString является переменным экземпляром со следующим свойством:

@property (nonatomic, retain) NSMutableString *tempString; 

tempString не должен быть выпущен в dealloc, как это начинается с удобством метод, поэтому он автоматически присваивается пулу авторезистов. Я также попробовал следующее с помощью метода alloc, init, но с тем же результатом. Итак, вот что я сделал:

1.) Запустите мой проект с помощью инструментов, пусть он ищет утечки сразу после запуска, их нет. 2.) запустите парсер XML один раз, проверьте на наличие утечек. Их нет. 3.) снова запустите XML Parser, теперь неожиданно вышла строка с [entryDict setObject:[tempString copy] forKey:kXMLDictDateKey];.

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

Ps. Мои проверки показывают, что между вызовами парсера (делегата) вызывается метод «dealloc», поэтому я думаю, что парсер действительно загружается два раза, а не один раз.

ответ

3

Ваш вызов:

tempString = [NSMutableString string]; 

На самом деле не ссылается свойство (обертка) и retain.

Вы должны сделать это вместо того, чтобы:

self.tempString = [NSMutableString string]; 

В противном случае вы просто установив Ивар непосредственно к autoreleased объекта.

Не только у вас есть утечка где-то, приведенный выше код в какой-то момент приведет к некоторому интересному сбою.

+0

Большое спасибо, это было то, чего мне не хватало. Теперь он работает как шарм :) – Robin

0

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

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

В этом случае, я думаю, что вам не хватает в том, что массив должен содержать объекты, которые autoreleased - так что вы хотите сказать:

[entryDict setObject:[[tempString copy] autorelease] forKey:kXMLDictDateKey]; 

Поскольку копирования также сохраняет копию (так же, как Alloc/инициализации бы).

+0

Большое спасибо за ваш быстрый ответ. Практика присоединения tempString к autorelease была скопирована из примера кода Apple в проекте «Производительность XML». Я добавил авторекламу, которую вы предложили, но я все еще получаю утечки. Почему tempString не получает должным образом освобожденную информацию, является для меня загадкой (я подозреваю, что это проблема?). Я также убедился, что «entryDict» будет выпущен, и это так, поэтому я думаю, что проблема действительно лежит в tempString. Есть ли у вас другая идея, что может вызвать утечку? Большое спасибо за ваши усилия! – Robin

+0

Какие релизы entryDict? Если это не будет выпущено, я могу увидеть, где будет сказано, что элементы внутри протекают. –

1

Другая ошибка в вашем коде:

[tempString appendString:[[XMLParser alloc] 
    stripUnwantedStringChars:string]]; 

Это выделяет новый XMLParser и никогда не избавляется от него.

+0

Да, вы правы, я забыл написать в описании, что XMLParser является синглом. Таким образом, это не создает новый экземпляр XMLParser, а возвращает только предыдущий. – Robin

+0

Лучший способ сделать это - следовать стилю Apple и использовать метод класса sharedEstance. Мессинг с 'alloc' для создания синглтона - это злой и очень плохой стиль imo. –

1

Я пытаюсь понять, что вы делали в своем назначении tempString. Если вы делаете это:

self.tempString = [NSMutableString string]; 

то сделать должны выпустить tempString в dealloc. Несмотря на то, что он автореализован, сеттер сохраняет его.

Смежные вопросы