При отпускании массива происходит сбой приложения в xCode - PullRequest
0 голосов
/ 07 февраля 2012

почему происходит сбой моего приложения при освобождении массива? Я пытался понять это в течение ЧАСОВ! Если я не выпускаю это, это вызывает утечку памяти. Если я выпущу его, он вылетает с этой ошибкой: Программа получила сигнал: «EXC_BAD_ACCESS». Иногда это также говорит это: Форматирование данных временно недоступно, повторная попытка после «продолжения». (В настоящее время небезопасно звонить длопену.)

Просто не могу разобраться. Theres много кода, поэтому я буду вставлять (что я думаю) соответствующие части.

-(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 Ответ

1 голос
/ 07 февраля 2012

Скорее всего, вы где-то добавили CharGuard объект к массиву charGuardStore, который сохраняется только этим массивом и суперпредставлением charGuards.

Вот что я думаю:

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 , чтобы выяснить, так ли это.

Я думаю, что если вы добавите [charGuardToDestroy removeAllObjects]; после удаления charGuards из этого массива, произойдет сбой.Это подтвердит то, что я сказал.

...