2010-10-05 128 views
2

僅供參考,我已經閱讀:EXC_BAD_ACCESS - 內存管理問題

而且我認爲他會幫助:)。

這個程序是一個教學工具,旨在幫助人們可視化簡單的遺傳學。只是一些背景,所以變量名稱和東西將有意義。下面是當應用程序運行執行主代碼:

- (void)viewDidAppear:(BOOL)animated { 
ThingzCore *core = [[ThingzCore alloc] init]; 

ThingzThing *thing1 = [[ThingzThing alloc] init]; 
thing1.breed = @"AB"; 
thing1.pattern = @"AC"; 
thing1.color = @"CA"; 
thing1.gender = @"XY"; 
thing1.generation = 1; 
thing1.isEgg = NO; 

ThingzThing *thing2 = [[ThingzThing alloc] init]; 
thing2.breed = @"CD"; 
thing2.pattern = @"BA"; 
thing2.color = @"CB"; 
thing2.gender = @"XX"; 
thing2.generation = 1; 
thing2.isEgg = NO; 

NSLog(@"Breeding GD BR PT CL G"); 

ThingzThing *child = [core mateFather:thing1 withMother:thing2]; 
NSLog(@"Round 1: %@ %@ %@ %@ %d",child.gender,child.breed,child.pattern,child.color,child.generation); 
sleep(10); 

child = [core mateFather:thing1 withMother:thing2]; 
NSLog(@"Round 2: %@ %@ %@ %@ %d",child.gender,child.breed,child.pattern,child.color,child.generation); 
sleep(10); 

child = [core mateFather:thing1 withMother:thing2]; 
NSLog(@"Round 3: %@ %@ %@ %@ %d",child.gender,child.breed,child.pattern,child.color,child.generation); 
sleep(10); 

child = [core mateFather:thing1 withMother:thing2]; 
NSLog(@"Round 4: %@ %@ %@ %@ %d",child.gender,child.breed,child.pattern,child.color,child.generation); 
sleep(10); 

[thing1 release]; 
[thing2 release]; 
[core release]; 
} 

而這裏的時候我以不同的方式運行它會發生什麼:

  • 運行沒有斷點,它崩潰,沒有控制檯消息,後第二次睡眠()但在「第三輪」NSLog之前。
  • 在啓用斷點的情況下運行,但沒有定義,它貫穿整個序列。在第四次睡眠()後,它與EXC_BAD_ACCESS一起崩潰。
  • 運行斷點啓用和NSZombiesEnabled,它做與上面相同的事情 - 沒有進一步的信息,只是EXC_BAD_ACCESS。
  • 在儀器中運行,沒有顯示泄漏。

這是例程被調用四次:

-(ThingzThing *)mateFather:(ThingzThing *)father 
     withMother:(ThingzThing *)mother { 
// will we be doing a mutation? 
int mutationPercentage = father.generation + mother.generation; 
int mutationNumber = (arc4random() % ((unsigned)100 + 1)); 
BOOL isMutation = NO; 
if (mutationNumber <= mutationPercentage) { 
    isMutation = YES; 
} 

// get possibilities 
NSArray *possibilities = [self possibilitiesByMatingFather:father 
               withMother:mother 
               mutations:isMutation]; 
// randomly select one of the possibilities 
int keeping = (arc4random() % ((unsigned)[possibilities count])); 
return [possibilities objectAtIndex:keeping]; 
} 

沒有在整個代碼粘貼,將possibilitiesByMatingFather:withMother:突變函數返回一個NSMutableArray。該例程通過使用聲明數組:

NSMutableArray *possibilities = [NSMutableArray array]; 

它然後:

return possibilities; 

它不發送釋放或自動釋放消息的可能性;我的理解是按照我的方式創建數組是一種隱式autorelease。我不想分配數組,因爲我正在返回它,所以沒有機會明確釋放它。

可能性NSMutableArray中保存的對象是自定義類。他們被添加如下:

ThingzThing *newThing = [[ThingzThing alloc] init]; 
newThing.breed = choiceBreed; 
newThing.gender = choiceGender; 
newThing.color = choiceColor; 
newThing.pattern = choicePattern; 
newThing.generation = mother.generation + father.generation; 
newThing.name = @""; 
newThing.isEgg = YES; 
[possibilities addObject:newThing]; 
[newThing release]; 

這似乎大部分時間工作。至少,當啓用斷點時,如上所述,程序直到最後才通過代碼運行,而無需投訴。

對我在做什麼錯的任何建議,在這裏?這顯然是某種類型的內存管理問題,但我無法在腦海中對其進行分類。

BTW,徒勞,投擲東西,在的牆試圖弄明白,我的確從主程序修改一個行,如下所示:

// get possibilities 
NSArray *possibilities = [[self possibilitiesByMatingFather:father 
               withMother:mother 
               mutations:isMutation] retain]; 

無濟於事。相同的結果。所以問題不在於保留由PossibleByMatingFather返回的數組:包含withMother:突變。強制留在那個回報沒有幫助。

+0

我知道這是一個愚蠢的問題,但可能導致錯誤。你能刪除所有的sleep()行嗎?呃...只是因爲我看不到你的代碼中有什麼不對) – vodkhang 2010-10-05 17:12:40

+0

它在第四次睡眠之後破裂了?這種方法離開後可能會引發異常嗎?請在此方法的最後一行添加一些NSLog-Foo – 2010-10-05 17:18:04

+0

嘗試用[[[[NSMutableArray alloc] init] autorelease]替換[NSMutableArray數組],看看會發生什麼...還發布possibleByMatingFather方法 – Daniel 2010-10-05 17:34:08

回答

1

在這種情況下,實際的錯誤並不在應用程序暫停時在調試器中顯示的位置。

例如,調試器可能指向一個方法調用,但問題實際上發生在方法內部 - 而不是調用該方法時。

爲了跟蹤事情,我建議在觸發錯誤的方法調用之前設置一個斷點 - 在你的情況下,這將是mateFather:withMother:call。然後進入該方法。您很可能會發現問題發生在該方法內部 - 或者甚至在該方法內部調用的方法內部。

+0

Bleh。調試器顯示它在蘋果的一些代碼中發現了它。堆棧顯示objc_msgSend,然後??,然後_CFAutoreleasePoolPop,然後[NSAutoreleasePool發佈]。所以我猜這是某種事情被雙重釋放的情況。必須挖掘。 – 2010-10-06 02:59:48

+0

接受這個是因爲它給了我一些線索讓我知道 - 實際的答案是(正如我發佈的),我釋放了一個也是自動釋放的對象 - 所以在調試器中加入了一些可愛的基礎二進制文件,並且EXC_BAD_ACCESS被一個試圖排空自身的自動釋放池拋出。 – 2010-10-06 03:06:14

0

檢查您是否擁有ThingzThing類的字符串屬性的正確屬性聲明。

例如

@property (nonatomic, retain) NSString* breed; 

需要被保留或複製品不分配...

+0

似乎是。唯一的賦值是兩個C類型,BOOL和int。所有的NSStrings都是非原子的,保留。 – 2010-10-06 02:46:17

0

發現了它。埋葬了八個方法調用,我正在發佈釋放到一個顯然是autoreleasing的NSArray。當初始調用例程(viewDidAppear)陷入自動釋放模式時,它試圖自動釋放已釋放的對象並爆炸。好悲傷 - XCode有什麼方法可以幫助我追蹤這種情況嗎?

在任何情況下,如果有人遇到這種情況,請確保你沒有發送釋放消息給你沒有明確地分配自己的東西。如果你沒有分配它,可能是它自己自動釋放,而你發送一個釋放給它會使保留計數爲負,並且Foundation框架會嘔吐一個EXC_BAD_ACCESS。