释放数组会使xCode中的应用程序崩溃

时间:2012-02-07 15:33:16

标签: arrays xcode crash nsmutablearray release

为什么我的应用程序在发布数组时会崩溃?我一直在试图解决这个问题!如果我不释放它,它会导致内存泄漏。如果我确实发布它,它会崩溃并出现此错误:     程序接收信号:“EXC_BAD_ACCESS”。 有时也说这个:     数据格式化程序暂时不可用,将在“继续”后重试。 (此时打电话给dlopen是不安全的。)

无法解决问题。有很多代码,所以我会粘贴(我认为)是相关部分。

-(void)startGame:(int)levelNumber {

    //NOTE there is some code ive not pasted as its too big, but I dont think its relevant

levelsArray = [gameLevels loadLevelMap:levelNumber];
levelsArray_charGuards = [[levelsArray objectAtIndex:4]retain];


    //CREATE CHAR MAIN ########
charMainStore = [[NSMutableArray arrayWithCapacity:1] retain];

charMainToDestroy = [[NSMutableArray arrayWithCapacity:1] retain];

CharMain* charMain = [[CharMain alloc] initWithFrame:CGRectMake(((levels_charStart_x)*40), ((levels_charStart_y)*40), 0, 0)];
[viewController.mapView addSubview:charMain];

[self registerMainChar:charMain];
charMain.gameController = self;
charMain.currentGrid_x = levels_charStart_x;
charMain.currentGrid_y = levels_charStart_y;
charMain.nextGrid_x = levels_charStart_x;
charMain.nextGrid_y = levels_charStart_y;
mapViewController.gameController = self;

[self moveMap_x:((levels_charStart_x)*40) moveMap_y:((levels_charStart_y)*40)];

[charMain release];

 //CREATE CHAR GUARD ######## 
charGuardStore = [[NSMutableArray arrayWithCapacity:10] retain];
charGuardToDestroy = [[NSMutableArray arrayWithCapacity:10] retain]; 
    //These are both @synthesize properly
    //levelsArray_charGuards is from previously

    for (NSMutableArray* levelsArray_charGuards_path in levelsArray_charGuards) {

    NSMutableArray* levelsArray_charGuards_path_eachCoOrd = [levelsArray_charGuards_path objectAtIndex:0];

    int levels_charGuardStart_x = [[NSString stringWithFormat:@"%@",[levelsArray_charGuards_path_eachCoOrd objectAtIndex:0]] intValue];
    int levels_charGuardStart_y = [[NSString stringWithFormat:@"%@",[levelsArray_charGuards_path_eachCoOrd objectAtIndex:1]] intValue];

    CharGuard* charGuard = [[CharGuard alloc] initWithFrame:CGRectMake((levels_charGuardStart_x*40), (levels_charGuardStart_y*40), 0, 0)];
    //CharGuard* charGuard = [[CharGuard alloc] initWithFrame:CGRectMake(((levels_charStart_x)*40), ((levels_charStart_y)*40), 0, 0)];

    [viewController.mapView addSubview:charGuard];

    [self registerGuardChar:charGuard];
    charGuard.gameController = self;
    [charGuard setImage];
    charGuard.currentGrid_x = levels_charGuardStart_x;
    charGuard.currentGrid_y = levels_charGuardStart_y;
    charGuard.nextGrid_x = levels_charGuardStart_x;
    charGuard.nextGrid_y = levels_charGuardStart_y;
    mapViewController.gameController = self;

    charGuard.levelsArray_charGuards_path = levelsArray_charGuards_path;

    [charGuard release];
    charGuard = nil;


    levelsArray_charGuards_path = nil;

    levelsArray_charGuards_path_eachCoOrd =nil;
}
}

当一个级别完成或重新启动时,这称为:

-(void)clearLevel {
NSLog(@"Clear Level");

    for (CharMain* charMain in charMainStore){

    [charMain removeFromSuperview];
    [charMainToDestroy addObject:charMain];
}

for (CharMain* charMain in charMainToDestroy){

    [charMainStore removeObject:charMain];

}

for (CharGuard* charGuard in charGuardStore) {

    [charGuard removeFromSuperview];
    [charGuardToDestroy addObject:charGuard];

}

for (CharGuard* charGuard in charGuardToDestroy){

    [charGuardStore removeObject:charGuard];

}

    [charGuardStore release];
charGuardStore=nil;

[charMainStore release];
charMainStore=nil;

//[charGuardToDestroy release]; //If I allow this it crashes!***********
charGuardToDestroy= nil;

[charMainToDestroy release];
charMainToDestroy = nil;

}

然后游戏再次调用startGame:(int)levelNumber。

我还有其他对象,我在这里展示但是它们都运行良好。它只是不想发布的charGuardToDestroy!

我试过了:

-(void)clearLevel {
NSLog(@"Clear Level");

    for (CharMain* charMain in charMainStore){

    [charMain removeFromSuperview];
    [charMainToDestroy addObject:charMain];
}

for (CharMain* charMain in charMainToDestroy){

    [charMainStore removeObject:charMain];

}

for (CharGuard* charGuard in charGuardStore) {

    [charGuard removeFromSuperview];
    //[charGuardToDestroy addObject:charGuard];

}
/*
for (CharGuard* charGuard in charGuardToDestroy){

    [charGuardStore removeObject:charGuard];

}
    */

    [charGuardStore release];
charGuardStore=nil;

[charMainStore release];
charMainStore=nil;

[charGuardToDestroy release]; //I tried allowing this and removing the above code ***********
charGuardToDestroy= nil;

[charMainToDestroy release];
charMainToDestroy = nil;

}

这也有效,但为什么?我真的需要能够从屏幕和阵列中删除charGuard,然后释放它,但我只能做其中一个。很奇怪!

1 个答案:

答案 0 :(得分:1)

你很可能在某个地方向charGuardStore数组添加了一个CharGuard对象,该数组仅由此数组和charGuards superview保留。

以下是我的想法:

for (CharGuard* charGuard in charGuardStore) {

    [charGuard removeFromSuperview];             // charGuard only retained by charGuardStore (= 1 retain left)
    [charGuardToDestroy addObject:charGuard];    // charGuard retained by charGuardToDestroy too (= 2 retains left)

}

for (CharGuard* charGuard in charGuardToDestroy){

    [charGuardStore removeObject:charGuard];     // remove 1 retain (= 1 retain left) because it's still in charGuardToDestroy

}

/* more code */

[charGuardToDestroy release];                    // remove all charGuards. charGuard gets released. And most likely you access it later. 

因此,当您创建CharGuards时,很可能已经发生了错误。可能过度释放,但效果会在很晚之后出现。

使用NSZombieEnabled确定是否属于这种情况。

我认为如果在从该阵列中删除charGuards后添加[charGuardToDestroy removeAllObjects];,它将崩溃。这将证实我说的话。