EXC_BAD_ACCESS Переход сцены SpriteKit, без зомби

У меня сбой, вызванный EXC_BAD_ACCESS. Он не перехватывается установкой NSZombieEnabled в YES, что указывает на то, что это не освобожденный объект. (Мальчик, я действительно хочу, чтобы это было)

Трассировка стека менее чем полезна (для меня). Кто-нибудь видит в этом какое-то понимание?

неверный адрес

трассировка стека

SpriteKit`std::__1::__tree_iterator<SKCSprite*, std::__1::__tree_node<SKCSprite*, void*>*, long> std::__1::__tree<SKCSprite*, std::__1::less<SKCSprite*>, std::__1::allocator<SKCSprite*> >::find<SKCSprite*>:
    0x1890c376c <+0>:  ldr    x9, [x0, #8]!
    0x1890c3770 <+4>:  cbz    x9, 0x1890c37b8           ; <+76>
    0x1890c3774 <+8>:  ldr    x10, [x1]
    0x1890c3778 <+12>: mov    x8, x0
->  0x1890c377c <+16>: ldr    x11, [x9, #32]
    0x1890c3780 <+20>: cmp    x11, x10
    0x1890c3784 <+24>: b.hs   0x1890c3794               ; <+40>
    0x1890c3788 <+28>: ldr    x9, [x9, #8]
    0x1890c378c <+32>: cbnz   x9, 0x1890c377c           ; <+16>
    0x1890c3790 <+36>: b      0x1890c37a0               ; <+52>
    0x1890c3794 <+40>: mov    x8, x9
    0x1890c3798 <+44>: ldr    x9, [x9]
    0x1890c379c <+48>: cbnz   x9, 0x1890c377c           ; <+16>
    0x1890c37a0 <+52>: cmp    x8, x0
    0x1890c37a4 <+56>: b.eq   0x1890c37b8               ; <+76>
    0x1890c37a8 <+60>: ldr    x9, [x1]
    0x1890c37ac <+64>: ldr    x10, [x8, #32]
    0x1890c37b0 <+68>: cmp    x9, x10
    0x1890c37b4 <+72>: b.hs   0x1890c37bc               ; <+80>
    0x1890c37b8 <+76>: mov    x8, x0
    0x1890c37bc <+80>: mov    x0, x8
    0x1890c37c0 <+84>: ret    

Другой контекст:

Приложение SpriteKit, которое переходит на новую сцену. Сначала отображается новая сцена, но сразу же происходит сбой.

Действие происходит как на входящих, так и на исходящих сценах. Эти действия содержат блок, который ссылается на сцену. Протекали сцены и этот блок оказался одним из нарушителей. Когда я добавил код для удаления действия, возник этот сбой.

Xcode 6.4 iPad Air, iOS 8.4.1


Редактировать 1: этот код существует в каждой SKScene. Когда второй метод закомментирован, он скрывает проблему (я полагаю, помогая утечке).

- (void)startAutoScore {
  // as long as you survive, you gradually accumulate points
  SKAction *autoScore = [SKAction runBlock:^{
    [self adjustScoreBy:1];
  }];

  NSTimeInterval duration = 0.25;
  SKAction *slice = [SKAction sequence:@[[SKAction waitForDuration:duration], autoScore]];
  SKAction *repeat = [SKAction repeatAction:slice count:self.fieldDescriptor.duration / duration - 1];
  [self runAction:repeat withKey:@"autoScore"];
}

- (void)stopAutoScore {
//  [self removeActionForKey:@"autoScore"];
}

Редактировать 2: я подтвердил с помощью Instruments, что при выполнении метода stopAutoScore последняя оставшаяся ссылка на используемый SKScene удаляется, а старая сцена корректно освобождается.


person bshirley    schedule 03.09.2015    source источник
comment
Можете ли вы обновить вопрос с фактическим кодом (часть, которую вы считаете актуальной), просто для полноты, потому что таким образом более вероятно, что вы получите лучший ответ.   -  person Whirlwind    schedule 03.09.2015
comment
Я не могу знать, какая часть моего кода является важной частью. Смотрите первое изображение. Он ломается в main(), а трассировка стека представляет собой несимволизированный машинный код, внутренний для SpriteKit. Я хотел бы иметь некоторый код, связанный с ним.   -  person bshirley    schedule 03.09.2015
comment
@whirlwind я добавил некоторый код, но не верю, что он вызывает проблему, скорее скрывая ее, когда сцена останавливается раньше и код не закомментирован, происходят сбои   -  person bshirley    schedule 03.09.2015
comment
Хорошо, я посмотрю на это позже, когда сяду за компьютер... Единственное, что я вижу, это то, что, возможно, у вас есть возможность сохранить цикл. Попробуйте переопределить метод Dealloc сцены и посмотрите, вызывается ли он (сделайте это и в обеих сценах).   -  person Whirlwind    schedule 03.09.2015
comment
Можете ли вы установить обработчик необработанных исключений в AppDelegate и посмотреть, не возникнет ли там какая-нибудь ошибка? Поместите следующее выше @implementation AppDelegate: static void UncaughtExceptionHandler(NSException *exc) { NSLog(@%@, exc.callStackSymbols); } А это в didFinishLaunching: NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);   -  person Josip B.    schedule 03.09.2015
comment
@bshirley- Попробуйте установить точку останова для всех исключений и посмотрите, где в вашем коде возникает ошибка.   -  person sangony    schedule 03.09.2015
comment
@Josip, это дает мне ту же информацию, что и отладчик.   -  person bshirley    schedule 04.09.2015
comment
@sangony, у меня уже была установлена ​​точка останова для всех исключений.   -  person bshirley    schedule 04.09.2015


Ответы (1)


У меня есть текущий (не идеальный) обходной путь.

Если я преобразую переход из особенно сложного SKScene в прямой presentScene:

от:

SKTransition *transition = [SKTransition fadeWithColor:[SKColor whiteColor] duration:1.0];
[self.view presentScene:scene transition:transition];

to:

[self.view presentScene:scene];

и если я явно удалю всех дочерних элементов из сцены, подлежащей замене, до вызова 'presentScene'

[self removeAllChildren];

Затем сбои (недетерминированные, но частые, по крайней мере, к 4-му такому переходу) прекращаются.

Учитывая это, я бы посчитал это внутренней ошибкой SpriteKit или каким-то образом я неправильно управляю спрайтами. Я хотел бы получить правильный ответ.

person bshirley    schedule 03.09.2015