iOS: не прекратит работу и не обработает много исключений - PullRequest
3 голосов
/ 27 марта 2011

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

Мой проект iPhone не будет ничего делать с NSExceptions при касании экрана при работе в течение нескольких секунд.

Когда это только началось, все нормально. Если (например) я вызываю исключение в моем коде здесь:

NSException *e = [NSException
        exceptionWithName:@"Testing"
        reason:@"Testing exception handling"
        userInfo:nil];
@throw e;
if (touched) {
}

... тогда исключение работает, как и ожидалось. Если я использовал NSSetUncaughtExceptionHandler, то вызывается мой & uncaughtExceptionHandler; если нет, я получаю SIGABRT, и программа завершается. Все хорошо.

Но если я заменим его следующим кодом (где touch затронут, то истина, если только что было touchchesBegan):

if (touched) {
    NSException *e = [NSException
            exceptionWithName:@"Testing"
            reason:@"Testing exception handling"
            userInfo:nil];
    @throw e;
}

... тогда мой код NSSetUncaughtExceptionHandler не вызывается, и сигнал SIGABRT не принимается. Кажется, он просто прекращает выполнение цикла выполнения и запускает следующий.

Если вы установите там точку останова и выполните 'step over' или 'step into', тогда он просто начнет работать, как если бы вы нажали продолжить (но без выполнения оставшейся части этого цикла выполнения).

То же самое происходит в разных классах. У меня нет попыток / ловит, которые могли бы захватить исключение NSException. Он ведет себя так же, если я делаю что-то вроде ...

[[NSArray array] objectAtIndex:1];

... сделать исключение. Это происходит одинаково и в симуляторе, и в устройстве.

Пожалуйста, помогите исключениям получить признание, которого они заслуживают!


В ответ на bbum вот обратная трассировка для 1-го случая выше, где исключение работает, как и ожидалось:

(gdb) BT
#0  -[Hud paintHudWithController:] (self=0x6475ee0, _cmd=0xbeb61, controller=0x686ac00) at /Users/mike/iPhone Dev/Parsec/Classes/Hud.m:2804
#1  0x00004f8e in -[ES1Renderer(Artist) paint] (self=0xa108a90, _cmd=0xc1b48) at /Users/mike/iPhone Dev/Parsec/Classes/ES1Renderer+Artist.m:92
#2  0x00003c22 in -[ES1Renderer render] (self=0xa108a90, _cmd=0x5f0dbb9) at /Users/mike/iPhone Dev/Parsec/Classes/ES1Renderer.m:81
#3  0x00003476 in -[EAGLView drawView:] (self=0xa103a70, _cmd=0xbe451, sender=0x64068a0) at /Users/mike/iPhone Dev/Parsec/Classes/EAGLView.m:79
#4  0x00c3c6a8 in CA::Display::DisplayLink::dispatch ()
#5  0x00c3c7ed in CA::Display::EmulatorDisplayLink::callback ()
#6  0x01494fe3 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ ()
#7  0x01496594 in __CFRunLoopDoTimer ()
#8  0x013f2cc9 in __CFRunLoopRun ()
#9  0x013f2240 in CFRunLoopRunSpecific ()
#10 0x013f2161 in CFRunLoopRunInMode ()
#11 0x000089e7 in -[Ticker tick] (self=0x686ac00, _cmd=0xbeb83) at /Users/mike/iPhone Dev/Parsec/Ticker.m:87
#12 0x00004e99 in -[ES1Renderer(Artist) paint] (self=0xa108a90, _cmd=0xc1b48) at /Users/mike/iPhone Dev/Parsec/Classes/ES1Renderer+Artist.m:67
#13 0x00003c22 in -[ES1Renderer render] (self=0xa108a90, _cmd=0x5f0dbb9) at /Users/mike/iPhone Dev/Parsec/Classes/ES1Renderer.m:81
#14 0x00003476 in -[EAGLView drawView:] (self=0xa103a70, _cmd=0xbe451, sender=0x0) at /Users/mike/iPhone Dev/Parsec/Classes/EAGLView.m:79
#15 0x000034ec in -[EAGLView layoutSubviews] (self=0xa103a70, _cmd=0x81b3de) at /Users/mike/iPhone Dev/Parsec/Classes/EAGLView.m:85
#16 0x00b80451 in -[CALayer layoutSublayers] ()
#17 0x00b8017c in CALayerLayoutIfNeeded ()
#18 0x00b7937c in CA::Context::commit_transaction ()
#19 0x00b790d0 in CA::Transaction::commit ()
#20 0x00ba97d5 in CA::Transaction::observer_callback ()
#21 0x01494fbb in __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ ()
#22 0x0142a0e7 in __CFRunLoopDoObservers ()
#23 0x013f2bd7 in __CFRunLoopRun ()
#24 0x013f2240 in CFRunLoopRunSpecific ()
#25 0x013f2161 in CFRunLoopRunInMode ()
#26 0x01de8268 in GSEventRunModal ()
#27 0x01de832d in GSEventRun ()
#28 0x0041e42e in UIApplicationMain ()
#29 0x000024a4 in main (argc=1, argv=0xbffff040) at /Users/mike/iPhone Dev/Parsec/main.m:13

и вот обратная трассировка для 2-го случая выше, где исключение очевидно съедено:

(gdb) BT
#0  -[Hud paintHudWithController:] (self=0x6469710, _cmd=0xbeb61, controller=0x6855000) at /Users/mike/iPhone Dev/Parsec/Classes/Hud.m:2806
#1  0x00004a36 in -[ES1Renderer(Artist) paint] (self=0x7922720, _cmd=0xc1b48) at /Users/mike/iPhone Dev/Parsec/Classes/ES1Renderer+Artist.m:92
#2  0x000036ca in -[ES1Renderer render] (self=0x7922720, _cmd=0x5f0dbb9) at /Users/mike/iPhone Dev/Parsec/Classes/ES1Renderer.m:81
#3  0x00002f1e in -[EAGLView drawView:] (self=0x7907de0, _cmd=0xbe451, sender=0x7926cd0) at /Users/mike/iPhone Dev/Parsec/Classes/EAGLView.m:79
#4  0x00c3c6a8 in CA::Display::DisplayLink::dispatch ()
#5  0x00c3c7ed in CA::Display::EmulatorDisplayLink::callback ()
#6  0x01494fe3 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ ()
#7  0x01496594 in __CFRunLoopDoTimer ()
#8  0x013f2cc9 in __CFRunLoopRun ()
#9  0x013f2240 in CFRunLoopRunSpecific ()
#10 0x013f2161 in CFRunLoopRunInMode ()
#11 0x01de8268 in GSEventRunModal ()
#12 0x01de832d in GSEventRun ()
#13 0x0041e42e in UIApplicationMain ()
#14 0x00001f4c in main (argc=1, argv=0xbffff040) at /Users/mike/iPhone Dev/Parsec/main.m:13

Ответы [ 5 ]

4 голосов
/ 05 апреля 2011

Я столкнулся с тем же самым в проекте OpenGL несколько недель назад.Это связано с тем, что ссылка на дисплей устанавливает обработчик исключений верхнего уровня.К сожалению, нет никакого способа обойти это, кроме как установить свой собственный обработчик исключений среднего уровня в обработчике ссылки на экран и сделать там прерывание (), если вы поймали исключение.

Работало для меня, по крайней мере.

дополнение: только что обнаруженная Core Animation также устанавливает обработчик исключений верхнего уровня.Проверьте «CoreAnimation: игнорирование исключения» в ваших журналах.

3 голосов
/ 27 марта 2011

Скорее всего, исключение происходит из-за того, что модальный цикл событий отслеживает касание. Сообщите об ошибке через http://bugreporter.apple.com/.

Как правило, исключения не должны использоваться для потока управления в iOS. Исключения следует рассматривать как неисправимые ошибки.

Вот почему это ошибка; как вы правильно предположили, исключение должно убить приложение.

2 голосов
/ 03 апреля 2011

Владелец метода приложения reportExceptions @implementation MyApplication

-(void) reportExceptions (NSException *)e
{
   @try {
   // show u expression here, [e callStackTrace] [e reason].   
   }
   @catch (NSExpression *)ee {   
    // u can be wrong in try also :-).   
   }
}

Не забудьте указать пользовательский подкласс приложения в plist Principal Class = MyApplication

1 голос
/ 31 марта 2011

пожалуйста, попробуйте принудительно сохранить ваши взгляды.[просмотр сохранить]

1 голос
/ 31 марта 2011

Возможно, это не решение, но может помочь в его поиске. Мой ответ состоит из 2 частей:

1) Попробуйте, чтобы увидеть, имеет ли это какое-либо значение.

NSException *e = [NSException
            exceptionWithName:@"Testing"
            reason:@"Testing exception handling"
            userInfo:nil];

 if (touched) {
   @throw e; 
}

Единственное различие, которое я вижу между двумя имеющимися у вас фрагментами кода, за исключением того факта, что вам нужно выбросить исключение внутри оператора if, состоит в том, что NSException объявлен внутри if.

2) Вы пытались это проверить, можно ли вообще перехватить исключение, когда оно выбрасывается внутри if?

@try {
  if (touched) {
    NSException *e = [NSException
            exceptionWithName:@"Testing"
            reason:@"Testing exception handling"
            userInfo:nil];
    @throw e;
  }
}
@catch (id anException) {
     NSLog(@"Exception: %@", [anException description]);
}

Или попробуйте это, чтобы увидеть, работает ли он не так, как приведенный выше код.

if (touched) {
  @try {
    NSException *e = [NSException
            exceptionWithName:@"Testing"
            reason:@"Testing exception handling"
            userInfo:nil];
    @throw e;
  }
  @catch (id anException) {
     NSLog(@"Exception: %@", [anException description]);
  }    
}

Пожалуйста, дайте мне знать, если вы найдете что-нибудь интересное (например, 2 фрагмента кода части 2 работают по-разному). Это поможет мне, когда я узнаю об исключениях и о том, как их ловить. В конце концов, мне нужно создать репортер для проекта, над которым я работаю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...