BAD_ACCESS при вызове дескриптора таймера

#nstimer #exc-bad-access #objective-c

#nstimer #исключение -bad-access #objective-c

Вопрос:

У меня есть такая реализация таймера в Timer.h /.mm

 @implementation Timer

static multiset<Timer *> timers;

- (void) run
{
    action();

    if (!repeat) 
    {
        timers.erase(timers.find(self));
    }
}

  (void) run: (Action) action after: (int) seconds repeat: (bool) rep
{
    Timer * timer = [[Timer alloc] init];

    timer->action = action;
    timer->repeat = rep;

    [NSTimer scheduledTimerWithTimeInterval:seconds
                                     target:timer
                                   selector:@selector(run)
                                   userInfo:nil
                                    repeats:rep];

    // timers.insert(timer);       // ANY version will fail
    timers.insert([timer retain]);
}

@end
  

После этого я вызываю его из своего UIViewController.mm:

 [Timer run:^ 
{ 
    // some code...
}
after:2];
  

Но он падает с EXC_BAD_ACCESS, когда приходит время без ввода [Запуск таймера]!

 #0  0x00000020 in ??
#1  0x000b87a5 in __NSFireTimer
#2  0x00dfafe3 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__
  

Что я делаю не так? Почему он вызывает cs:20h? У меня вообще нет такого значения (32) в моей программе!

После некоторых незначительных изменений таймер пытается вызвать

 #0  0x04ae6000 in ??
  

вместо

 #0  0x00000020 in ??
  

когда сегмент кода находится за пределами 0h(?) amp; ~ 15000h.

Ответ №1:

Я предполагаю, что вам нужно скопировать блок, run:after:repeat: потому что тот, который вы передаете, основан на стеке и уничтожается, когда область, в которой он находится, разматывается.