EXC_BAD_ACCESS внутри метода init с cocos2d - PullRequest
0 голосов
/ 14 марта 2012

Хорошо, ребята, у меня есть тот, который сбил меня с толку. Я немного искал ответ, но ничего, что я нашел, ничего не прояснило. Если я пропустил соответствующий ответ, примите мои извинения и укажите мне правильное направление. Тем не менее ...

Моя проблема - ошибка exc_bad_access, которая, как я знаю, обычно вызывается попыткой что-то сделать с объектом, у которого была освобождена память. Однако мое замешательство связано с тем фактом, что когда я пытаюсь создать экземпляр слоя (с помощью метода init), как только я пытаюсь установить любое из значений классов, возникает ошибка, о которой идет речь. Спрайт является членом суперкласса ... суперкласс наследуется от CCLayer. Почему говорится, что я пытаюсь получить доступ к памяти, которая была освобождена, когда мой слой был явно только что создан и для него выделена память? Есть ли решение, чтобы избавиться от этого сообщения об ошибке? Возможно, есть какая-то особенность наследования в цели c, о которой я не знаю?

Вот соответствующие методы из слоя, который я пытаюсь создать:

+(CCScene *) scene
{
    CCScene *scene = [CCScene node];

    //note that i allocate and initialize the object just like any other object
    //I've also tried retain here
    MainGameLayer *layer = [[MainGameLayer alloc] init];
    layer = [MainGameLayer node];

    HUD *hudLayer = [[HUD alloc] initWithLayer:layer];
    [scene addChild:hudLayer z:1];

    [scene addChild:layer];

    return scene;
}

-(id) init {
    //will call the init method shown below
    if (self=[super init]) {

        //program crashes right here on this line with exc_bad_access 
        centerBackground = [CCSprite spriteWithFile:@"background.png"];
        centerBackground.position = ccp(240, 160);
        [self addChild:centerBackground];

        eastBackground = [CCSprite spriteWithFile:@"background.png"];
        eastBackground.position = ccp(752, 160);
        [self addChild:eastBackground];

         westBackground = [CCSprite spriteWithFile:@"background.png"];
         westBackground.position = ccp(-272, 160);
         [self addChild:westBackground];

         northBackground = [CCSprite spriteWithFile:@"background.png"];
         northBackground.position = ccp(240, 672);
         [self addChild:northBackground];

         southBackground = [CCSprite spriteWithFile:@"background.png"];
         southBackground.position = ccp(240, -352);
         [self addChild:southBackground];
    }
    return self   
}

Вот интерфейс для суперкласса, от которого наследуется мой слой:

@interface GamePlayLayer : CCLayer <UIAccelerometerDelegate> {
    UIAccelerometer *accelerometer;
    float xAccelerationFactor;
    float yAccelerationFactor;
    float zAccelerationFactor;
    CCSprite *centerBackground;
    CCSprite *eastBackground;
    CCSprite *westBackground;
    CCSprite *southBackground;
    CCSprite *northBackground;
    CCSprite *southWestBackground;
    CCSprite *southEastBackground;
    CCSprite *northWestBackground;
    CCSprite *northEastBackground;
}

@property (nonatomic, retain) UIAccelerometer *accelerometer;
@property float xAccelerationFactor;
@property float yAccelerationFactor;
@property float zAccelerationFactor;

@end

... И метод инициализации суперкласса

- (id) init {
    //note that this init finishes with no problems
    xAccelerationFactor = 0;
    yAccelerationFactor = 0;
    zAccelerationFactor = 0;

    self.accelerometer = [UIAccelerometer sharedAccelerometer];
    self.accelerometer.updateInterval = .1;
    self.accelerometer.delegate = self;
}

Любая помощь или общие советы приветствуются. Большое спасибо заранее!

Ответы [ 2 ]

0 голосов
/ 14 марта 2012

Этот код должен выдавать предупреждение «Управление достигает конца не пустой функции»:

- (id) init {
    //note that this init finishes with no problems
    xAccelerationFactor = 0;
    yAccelerationFactor = 0;
    zAccelerationFactor = 0;

    self.accelerometer = [UIAccelerometer sharedAccelerometer];
    self.accelerometer.updateInterval = .1;
    self.accelerometer.delegate = self;
}

Вы объявляете init для возврата значения типа id. Вы ничего не возвращаете. Затем вы используете это ничто и присваиваете ему self здесь:

 if (self=[super init]) {

В лучшем случае невозвратное значение просто nil. Но это не потерпит крах. Итак, я полагаю, что происходит одна из двух вещей:

  • self остается неинициализированным со случайным значением.
  • self инициализируется возвращаемым значением из стека, но поскольку вы никогда не возвращали значение, возвращаемое значение является просто случайным значением.

Короче говоря: никогда, никогда не игнорируйте предупреждения, если вы не знаете, что делаете. Включите «Обрабатывать предупреждения как ошибки» в настройках сборки, это может быть весьма поучительной дисциплинарной мерой. :)

0 голосов
/ 14 марта 2012

Вы устанавливаете MainGameLayer *layer дважды. Первый alloc не нужен, и он улавливает память, потому что он не освобожден.

Изменить это:

MainGameLayer *layer = [[MainGameLayer alloc] init];
layer = [MainGameLayer node];

к этому:

MainGameLayer *layer = [MainGameLayer node];
...