2013-06-13 46 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'泄漏。這是泄漏的路徑和tutorialPath字典。順便說一句,你不需要在你的dealloc方法中設置這些變量爲零。很多人都這樣做,這是一種傳播的病毒反模式,但是如果有任何事情在對象被釋放之後試圖獲取對象的ivars,那麼你遇到的問題比是否ivars被拒絕出來了! –

回答

2

它看起來像我正在泄漏你的NSDictionary對象,正如靜態分析器指出的那樣。您不在任何地方存儲[[NSDictionary alloc] initWithContentsOfFile:path][[NSDictionary alloc] initWithContentsOfFile:tutorialPath]的結果,因此您無法發送這些對象的顯式發佈消息。

嘗試增加自動釋放調用中創建的中間字典後,如:

_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"];