Странная утечка памяти iPhone в парсере xml
-
06-07-2019 - |
Вопрос
Обновление : я редактировал код, но проблема сохраняется ...
Привет всем,
это мой первый пост здесь - я нашел это место отличным ресурсом для решения многих моих вопросов. Обычно я изо всех сил стараюсь что-то исправить самостоятельно, но на этот раз я действительно не знаю, что происходит не так, поэтому я надеюсь, что кто-то может мне помочь.
Я создаю приложение для iPhone, которое анализирует пару XML-файлов с помощью TouchXML. У меня есть класс XMLParser, который заботится о загрузке и разборе результатов. Я получаю утечки памяти, когда я анализирую XML-файл более одного раза с одним и тем же экземпляром XMLParser.
Вот один из фрагментов анализа (только соответствующая часть):
for(int counter = 0; counter < [item childCount]; counter++) {
CXMLNode *child = [item childAtIndex:counter];
if([[child name] isEqualToString:@"PRODUCT"])
{
NSMutableDictionary *product = [[NSMutableDictionary alloc] init];
for(int j = 0; j < [child childCount]; j++) {
CXMLNode *grandchild = [child childAtIndex:j];
if([[grandchild stringValue] length] > 1) {
NSString *trimmedString = [[grandchild stringValue] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
[product setObject:trimmedString forKey:[grandchild name]];
}
}
// Add product to current category array
switch (categoryId) {
case 0:
[self.mobil addObject: product];
break;
case 1:
[self.allgemein addObject: product];
break;
case 2:
[self.besitzeIch addObject: product];
break;
case 3:
[self.willIch addObject: product];
break;
default:
break;
}
[product release];
}
}
В первый раз, когда я анализирую xml, в приборах нет утечек, в следующий раз я получаю много утечек (NSCFString / NSCFDictionary).
Инструменты указывают мне на эту часть внутри CXMLNode.m , когда я копаюсь в просочившемся объекте:
theStringValue = [NSString stringWithUTF8String:(const char *)theXMLString];
if ( _node->type != CXMLTextKind )
xmlFree(theXMLString);
}
return(theStringValue);
Я действительно потратил много времени и попробовал несколько подходов, чтобы исправить это, но пока безрезультатно, может, я упускаю что-то важное? Р>
Любая помощь высоко ценится, спасибо!
Решение
Скорее всего, проблема в этой строке:
[self.mobil addObject:[product copy]];
Вызывая копию product
, вы создаете новый экземпляр NSMutableDictionary с счетчиком сохранения 1. Однако экземпляр mobil
будет увеличивать сохранение копии считается, когда вы отправляете ему сообщение addObject:
, поэтому количество сохраненных копий теперь равно 2. Вообще говоря, объект отвечает за обработку собственной памяти объекта, поэтому каждый раз, когда вы отправляете сообщение setFoo:
или addObject:
, вы можете просто передать объект напрямую, даже если он автоматически освобожден или вы планируете выпустить его сразу после вызова; ответственность за сохранение передаваемого объекта лежит на получателе, если он должен удерживать его.
Поскольку вы не присваивали копию какой-либо переменной, у вас нет указателя, который можно использовать для уменьшения счетчика хранения копии сейчас, когда она вам больше не интересна, поэтому даже если mobil Когда код> выпускает копию продукта в какой-то момент, она никогда не достигнет счетчика сохранения 0. Ваш оператор
[выпуск продукта]
в конце цикла for освобождает исходный product код> объект, а не копия, которую вы создали.
Вместо этого попробуйте следующее и посмотрите, подходит ли инструмент лучше:
[self.mobil addObject:product];
Другие советы
Проще говоря, каждый раз, когда вы используете copy
, вы также должны где-то использовать release
/ autorelease
.
И в этом случае, еще более простой ответ - не использовать copy
, поскольку вы ничего не делаете с оригинальной версией product
после Вы скопировали это.
Я сам решил проблему. Это было довольно глупо, но, возможно, кто-то может столкнуться с тем же, поэтому я собираюсь опубликовать это здесь. Р>
1) У меня был изменяемый массив, настроенный как переменные экземпляра, например:
@interface XMLParser : NSObject {
// ...
NSMutableArray *mobil;
// ...
}
@property(nonatomic, retain) NSMutableArray *mobil;
@end
Каждый раз, когда я хотел восстановить новые данные внутри, я делал:
self.mobil = ноль;
Что не то, что я хотел сделать, так что это лучший подход:
[self.mobil removeAllObjects]; Р>
2) Метод dealloc должен быть таким, чтобы исправить утечки (потому что mobil определяется как свойство):
- (недействительно) dealloc {
[мобил релиз];
self.mobil = ноль;
}
Уфф, это было много работы, чтобы выяснить - надеюсь, это спасет кого-то еще некоторое время :-)