Утечка памяти с NSMutableString appendString - PullRequest
3 голосов
/ 13 января 2010

Я использую XMLParser для анализа некоторых данных XML, который использует NSMutableString * resultString для хранения символов тега. В каждом (- parser: didStarElement ...) методе, который я выделяю и инициирую resultString-ivar.

-  (void)parser: (NSXMLParser *)parser didStartElement: (NSString *)elementName namespaceURI: (NSString *)namespaceURI qualifiedName: (NSString *)qName attributes: (NSDictionary *)attributeDict { 
// Alot of if-statements to sort subtags
// /.../
    resultString = [[NSMutableString alloc] init];
    recordResults = YES;
}

Строка добавляется в анализатор: foundCharacters-method. Я где-то читал, что автоматически выпущенные объекты, такие как строка в appendString, могут вызвать утечку памяти. Поэтому я добавил локальный пул авто-релиза, чтобы убедиться, что он сразу же истощился (однако никаких изменений в поведении):

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if(recordResults) {
    [resultString appendString: string];
}
[pool drain];
}

В парсере: didEndElement ... Я, наконец, освобождаю и обнуляю результирующую строку:

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

   // Alot of if statements to handle differnt tags
   // each of which has the structure of the last else-statement
   // In other words, I am pretty sure I've covered every possible
   // case to prevent the resultString from
   // not getting released and niled out
    if(...) {
            ...
}
    else if(...) {
            ...
    }
else {
    if(resultString != nil) {
        [dataDict setObject: resultString forKey: elementName];
        [resultString release];
        resultString = nil;
    }
}

Instruments Leak-tool помечает синтаксический анализатор: foundCharacter-method как источник утечки памяти, поэтому мне интересно, вызвано ли это appendString. Или, если вы можете найти что-то в этом коде, это неправильно. Это довольно требовательное к памяти приложение, анализирующее довольно много, а иногда и довольно больших XML-файлов на iPhone, поэтому мой вопрос заключается в том, как найти обходной путь, если NSMutableString appendString не подходит в этом случае ...

Заранее спасибо!

Ответы [ 3 ]

3 голосов
/ 13 января 2010

Если конечный тег отсутствует, у вас будет утечка памяти. Лучше иметь какие-либо выделения в parserDidStartDocument: и освобождения в parserDidEndDocument:, поскольку они гарантированно сопряжены. И вместо того, чтобы размещать resultString в didStartElement, вы просто обрезаете его там.

0 голосов
/ 13 января 2010

Пул автоматического выпуска ничего не делает, так как вы не выпускаете автоматически какие-либо объекты - вы размещаете изменяемую строку в одном месте, освобождая ее в другом. "appendString" вообще ничего не делает для сохранения счетчика MutableString.

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

Так что в какой-то момент позже может показаться, что вы извлекаете resultString из dataDict, в который вы его помещаете, сохраняете его и не освобождаете его (мне кажется, что вы выпустите его нормально при разборе, чтобы это не было причиной ). Чтобы убедиться, что это так, измените вставку строки на ::

 [dataDict setObject:[[resultString copy] autorelease] forKey: elementName];

И утечки должны сказать вам, что утечка есть. Чтобы помочь отследить утечку, каждый раз, когда вы извлекаете строку из этого dataDict, вы можете [скопировать] ее, и тогда вы приблизитесь к точному коду, который пропускает строки.

По сути, «Утечки» подобны раскрытию книги о тайнах с кем-то мертвым. Вы должны выяснить, кто убийца - или в случае утечек, кто должен был совершить убийство, но не удосужился.

0 голосов
/ 13 января 2010

Не думаю, что вы можете знать, использует ли appendString autorelease или нет, потому что метод изменяет свой объект, а не возвращает новый объект. Другими словами, поскольку он сам меняется, вы не несете ответственности за управление памятью. Вам также не принадлежит string, поэтому вам не нужно выпускать или автоматически выпускать его.

Проверьте это: http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994-BAJHFBGH

Это, вероятно, прояснит ситуацию, но главное в autorelease - это то, что "новые" объекты, возвращаемые чем-то, кроме alloc / init, автоматически освобождаются. В этом случае новый объект не возвращается с помощью appendString, и строка может быть просто сохранена, передана в обратный вызов синтаксического анализатора, а затем освобождена вызывающей стороной, поэтому кто знает, автоматически ли это освобождено.

Время, когда вам нужно что-то автоматически высвобождать, это когда у вас есть функция / метод, который использует alloc / new / copy, а затем возвращает объект без возможности для самой функции выпустить его в будущем.

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