2009-04-21 111 views
0

我一直在盯着這個相同的問題很長一段時間了,並會真正感謝任何幫助或建議。我確定它很簡單,但我似乎無法找到它。在我的應用程序委託我加載了一堆輔助對象(一個對象,我創建,它支持NSCopying)用下面的代碼:iPhone SDK內存管理問題 - EXC_BAD_ACCESS

NSString  *path = [[NSBundle mainBundle] pathForResource:@"Accessories" ofType:@"plist"]; 
NSDictionary *accDict = [[NSDictionary alloc] initWithContentsOfFile:path]; 

self.colors = (NSArray *) [accDict objectForKey:@"Colors"]; 
self.exteriorAccessories = [self loadAccessoriesForMode:EXTERIOR_MODE withDictionary:accDict]; 
self.interiorAccessories = [self loadAccessoriesForMode:INTERIOR_MODE withDictionary:accDict]; 
[accDict release]; 

這是定義的方法調用它的:

-(NSArray *)loadAccessoriesForMode:(NSString *)mode withDictionary:(NSDictionary *) dictionary 
{ 
    NSMutableArray *tempValues = [[NSMutableArray alloc] init]; 
    for (NSDictionary *value in [dictionary objectForKey:mode]) 
    { 
     Accessory *accessory = [[Accessory alloc] initWithDictionary:value]; 
     [tempValues addObject:accessory]; 
     [accessory release]; 
    } 

    NSArray *returnArray = [[NSArray alloc] initWithArray:tempValues copyItems:YES]; 
    [tempValues release]; 
    [returnArray autorelease]; 

    return returnArray; 
} 

當我開始使用accDict時,我收到了一個EXC_BAD_ACCESS異常。如果我在循環中取出配件的發佈版,一切都很好 - 但是我泄漏了Accessory對象(這對我來說似乎是obv。 - 如果我初始化並分配了它,那麼我的工作就是釋放它)。

當我在調試器中逐步完成此操作時,我發現init,copy和dealloc方法都會按照預期在我的Accessory對象上觸發。如果您認爲它會有所幫助,我也可以發佈Accessory對象的代碼,但我認爲問題出現在此代碼中。

回答

3

我想我已經找到了原因,但我會在這裏發佈,以便其他人可能會受益。這與我發佈的代碼沒有任何關係。問題在於Accessory對象內部。我直接設置的東西,而不是通過自我調用getters。

所以這樣的:

value = [dict objectForKey:@"myKey"]; 

取而代之的是:

self.value = [dict objectForKey:@"myKey"]; 

不知怎的,這是使我對的NSDictionary本身不好的副作用(我認爲這是不可變的,但它似乎我不知怎的搞砸了)。我發現的唯一方法是使用非常有用的建議that I found on Cocoa With Love

當我在XCode中使用打印描述選項時,我能夠看到NSDictionary以某種方式包含了AccessoryValue對象 - 我的自定義對象之一,因爲這只是從簡單的plist加載的,所以不應該出現在那裏。可以在XCode中找到打印描述,方法是將鼠標懸停在對象上以查看其詳細信息(在調試器中暫停過程時),然後單擊展開爲對象詳細信息的三角形旁邊的小上/下箭頭。對於字典,這會將其全部內容轉儲到控制檯。

+0

知道屬性「value」是如何定義的以及訪問方法中發生了什麼很重要。那裏有保留和發佈嗎? – 2009-04-21 02:37:39

0

請前綴,它是「我什麼都不知道目標C,但」:

在我看來像你需要釋放附件的項目,你讓他們複製到「returnArray」之後,或許不是指定「copyItems」。

0

在您的代碼上運行Clang。這是天賜之物。鏗鏘的規則!它會對你的代碼進行靜態分析,告訴你你可能會泄漏什麼。好東西。

0

我正在與Exc_Bad_Access問題爭鬥一天,最後找到答案。問題是當我嘗試訪問NSDictionary中存儲的對象之一時,第一次是正常的,但第二次訪問時對象變爲零,即使對象在字典中計數保持不變。這種奇怪的行爲是由於釋放對象兩次。下面是一個例子:

NSString * nstring = [[[NSString alloc] init] autorelease] [AnNSDictonaryInstance setObject:nstring forKey:0];

... [nstring release];

請注意,nstring被設置autorelease然後再次釋放?它不會立即顯示問題,您嘗試第二次讀取字典對象。我希望有一天蘋果的開發團隊能夠在編譯時將其標記爲違規行爲。

我希望這篇文章能幫助別人。

Wayne of Campbell