2013-06-13 3 views
1

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

NSString *path = nil; 
NSString *tutorialPath = nil; 
if (CC_CONTENT_SCALE_FACTOR() == 2) 
{ 
    path = [[NSBundle mainBundle] pathForResource:@"sheetObjects-hd" ofType:@"plist"]; 
    tutorialPath = [[NSBundle mainBundle] pathForResource:@"sheetTutorial-hd" ofType:@"plist"]; 
} else 
{ 
    path = [[NSBundle mainBundle] pathForResource:@"sheetObjects" ofType:@"plist"]; 
    tutorialPath = [[NSBundle mainBundle] pathForResource:@"sheetTutorial" ofType:@"plist"]; 
} 

_animDataDictionary = [[[NSDictionary alloc] initWithContentsOfFile:path] objectForKey:@"frames"]; 
_tutorialAnimDataDictionary = [[[NSDictionary alloc] initWithContentsOfFile:tutorialPath] objectForKey:@"frames"]; 

Проблема была с этими двумя линиями:

_animDataDictionary = [[[NSDictionary alloc] initWithContentsOfFile:path] objectForKey:@"frames"]; 
_tutorialAnimDataDictionary = [[[NSDictionary alloc] initWithContentsOfFile:tutorialPath] objectForKey:@"frames"]; 

Я проверил мой dealloc код, и я уверен, что они dealloced правильно.

И это, как я определил случаи:

NSDictionary *_animDataDictionary; 
NSDictionary *_tutorialAnimDataDictionary; 

dealloc функции:

[_animDataDictionary release]; 
_animDataDictionary = nil; 
[_tutorialAnimDataDictionary release]; 
_tutorialAnimDataDictionary = nil; 
[super dealloc]; 

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

У меня есть тонны утечек, связанных с этим кодом, и я чувствую, что это необходимо, чтобы убить его.

Спасибо!

+1

Я подозреваю, что вы не используете автоматический подсчет ссылок , Это правильно? Если да, почему бы вам не включить автоматический подсчет ссылок? –

+0

Только что внесли изменения, добавив функции dealloc в вопросы. Да, вы правы, я не использую ARC, потому что это старый, а также мой первый проект ios. Я решил не использовать ARC, чтобы я мог практиковать управление памятью iOS. – zeroliu

+0

Я отредактировал свой комментарий. Я понял, что после того, как я опубликовал свой оригинальный комментарий, что это не '_animDataDictionary' или' _tutorialAnimDataDictionary', который протекает. Это теги path и tutorialPath, которые протекают. Кстати, вам не нужно устанавливать эти переменные в нуль в методе dealloc. Многие люди делают это, это своего рода вирусный анти-шаблон, который распространяется вокруг, но если что-то пытается добраться до иваров вашего объекта после того, как объект был освобожден, у вас возникают большие проблемы, чем то, вне! –

ответ

2

Мне кажется, что вы протекаете объекты NSDictionary, как указал статический анализатор. Вы не сохраняете результат [[NSDictionary alloc] initWithContentsOfFile:path] или [[NSDictionary alloc] initWithContentsOfFile:tutorialPath] в любом месте, чтобы вы не могли отправлять эти сообщения с явным сообщением о выпуске.

Попробуйте добавить autorelease вызовов после создания этих промежуточных словарей, как:

_animDataDictionary = [[[[NSDictionary alloc] initWithContentsOfFile:path] autorelease] objectForKey:@"frames"]; 
_tutorialAnimDataDictionary = [[[[NSDictionary alloc] initWithContentsOfFile:tutorialPath] autorelease] objectForKey:@"frames"]; 
+0

Вот и все !!! Как вы должны найти эту утечку! Большое спасибо! – zeroliu

+1

+1 Это верно.Альтернативной (и немного более читаемой версией) будет '[NSDictionary dictionaryWithContentsOfFile: path]' – Alladinian

+0

@zeroliu, @Alladinian: Да, на самом деле, используя '[NSDictionary dictionaryWithContentsOfFile:]', вероятно, путь сюда. Он работает так же, как '[[NSDictionary alloc] initWithContentsOfFile: ] autorelease]', но более читаем, как отметил @ Alladinian. –

0

первый: вы уверены, что ваш метод dealloc называется? добавьте в него NSLog, чтобы убедиться, что ваш класс освобожден. Если нет, проблема не в коде этого класса, а в коде класса, который использует (выделяет/создает) его.

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

_animDataDictionary = [[[NSDictionary alloc] initWithContentsOfFile:path] objectForKey:@"frames"]; 
_tutorialAnimDataDictionary = [[[NSDictionary alloc] initWithContentsOfFile:tutorialPath] objectForKey:@"frames"]; 

в этом последнем случае необходимо освободить 2 словаря, прежде чем создавать новые:

[_animDataDictionary release]; // the first time it's = nil, and calling this line has no problem anyway 
_animDataDictionary = [[[NSDictionary alloc] initWithContentsOfFile:path] objectForKey:@"frames"]; 
[_tutorialAnimDataDictionary release]; 
_tutorialAnimDataDictionary = [[[NSDictionary alloc] initWithContentsOfFile:tutorialPath] objectForKey:@"frames"]; 
Смежные вопросы