Управление ответом программы на исключения

Этот документ описывает некоторые пользовательские значения по умолчанию и API платформы Обработки исключений, которую можно использовать для управления поведением приложений в ответ на определенные типы ошибок.

Для использования служб платформы Обработки исключений в проекте Какао (или приложение или неприложение) добавить ExceptionHandling.framework в /System/Library/Frameworks к Вашему проекту XCode. Также вставьте следующую директиву импорта в заголовок или файл реализации класса, использующего платформу:

#import <ExceptionHandling/NSExceptionHandler.h>

Ошибки приложения

Определенные типы ошибок приложения обычно заставляют приложения Какао выходить резко. Можно использовать пользовательское значение по умолчанию, NSExceptionHandlingMask, управлять этим поведением (для Приложения только Основанные на наборе приложения) для трех из наиболее распространенных классов таких ошибок:

Для этих ошибочных типов можно установить NSExceptionHandlingMask сделать одно из следующих действий:

Вы создаете маску путем добавления значений, соответствующих типам ошибок, которые будут зарегистрированы или обработаны:

Табличные 1  константы Обработки исключений и defaults значения

Тип действия

Постоянный

Значение для defaults

Зарегистрируйте непойманный NSExceptions

NSLogUncaughtExceptionMask

1

Обработайте непойманный NSExceptions

NSHandleUncaughtExceptionMask

2

Исключения системного уровня журнала

NSLogUncaughtSystemExceptionMask

4

Исключения системного уровня дескриптора

NSHandleUncaughtSystemExceptionMask

8

Зарегистрируйте ошибки периода выполнения

NSLogUncaughtRuntimeErrorMask

16

Обработайте ошибки периода выполнения

NSHandleUncaughtRuntimeErrorMask

32

Таким образом, если Вы вводите следование командной строки (в Терминальном приложении):

defaults write NSGlobalDomain NSExceptionHandlingMask 63

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

Слово «дескриптор» в константах обработки исключений имеет определенное значение в зависимости от типа исключения. Платформа Обработки исключений обрабатывает исключения системного уровня и ошибки периода выполнения путем преобразования их в NSException объекты. Эти объекты исключения содержат отслеживание стека в их userInfoсловарь под ключом NSStackTraceKey. Непойманные дескрипторы платформы NSException объекты путем завершения потока, в котором они происходят. Исключения на основном потоке приложения Какао пойманы обработчиками верхнего уровня, обычно устанавливающимися Набором Приложения.

Вместо NSExceptionHandlingMask пользовательское значение по умолчанию, можно использовать setExceptionHandlingMask: метод платформы Обработки исключений для получения того же поведения обработки исключений. И для приложения и для неприложения исполнимые программы Какао, соединитесь против платформы Обработки исключений и отправьте следующее сообщение:

[[NSExceptionHandler defaultExceptionHandler] setExceptionHandlingMask: aMask]

aMask параметр является небольшим количеством маски, составленной поразрядным осуществлением операции ИЛИ константы, перечисленные в таблице выше. Посмотрите заголовочные файлы платформы Обработки исключений для большего количества подробных данных о NSExceptionHandler API.

Отладка Средств

Для отладки целей также возможно использовать те же механизмы для создания отчетов относительно NSExceptions, который был бы иначе пойман. Можно также использовать любого NSExceptionHandlingMask свойство defaults система с этой целью или setExceptionHandlingMask: метод класса NSExceptionHandler. Связанные константы и значения перечислены в следующей таблице:

Табличные 2  константы Отладки и defaults значения

Тип действия

Постоянный

Значение для defaults

Исключения журнала, которые были бы пойманы обработчиками исключений верхнего уровня в NSApplication. Посмотрите примечание ниже.

NSLogTopLevelExceptionMask

64

Исключения дескриптора, которые были бы пойманы обработчиками исключений верхнего уровня в NSApplication

NSHandleTopLevelExceptionMask

128

Исключения журнала, которые будут пойманы на более низких уровнях

NSLogOtherExceptionMask

256

Исключения дескриптора, которые будут пойманы на более низких уровнях

NSHandleOtherExceptionMask

512

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

В дальнейших целях отладки можно изменить поведение обработки для любого условия, обработанного NSExceptionHandler так, чтобы приложение было вместо этого остановлено так, отладчик может быть присоединен. Можно управлять этим поведением с суммированными значениями для NSExceptionHangingMask пользовательское значение по умолчанию или с битовой маской, переданной в setExceptionHangingMask: из класса NSExceptionHandler. В следующей таблице перечислены допустимые константы и defaults значения:

Тип действия

Постоянный

Значение для defaults

Зависните для неперехваченных исключений

NSHangOnUncaughtExceptionMask

1

Зависните для исключений системного уровня

NSHangOnUncaughtSystemExceptionMask

2

Зависните для ошибок периода выполнения

NSHangOnUncaughtRuntimeErrorMask

4

Зависните для перехваченных исключительных ситуаций верхнего уровня

NSHangOnTopLevelExceptionMask

8

Зависните для других перехваченных исключительных ситуаций

NSHangOnOtherExceptionMask

16

Печать символьных отслеживаний стека

Как средство отладке, можно использовать atos утилита командной строки для преобразования числовых отслеживаний стека в символьную форму. (См. atos(1) страница справочника для подробных данных этой утилиты командной строки.)

Вместо того, чтобы переключить между XCode Терминальную оболочку, можно добавить код к использующей программе atos распечатать символьное отслеживание стека к консоли. Перечисление 1 показывает, как Вы делаете это. Метод printStackTrace: извлекает (числовое) отслеживание стека из переданного - в NSException возразите и затем создайте NSTask объект, представляющий atos команда с отслеживанием стека в качестве параметра. Это запускает подзадачу, и получающийся символьный след распечатан к стандартному выводу (который является выполнением, входят в систему XCode).

Перечисление 1  метод, распечатывающий символьную заднюю трассировку исключения

- (BOOL)exceptionHandler:(NSExceptionHandler *)sender shouldLogException:(NSException *)exception mask:(unsigned int)mask
{
    [self printStackTrace:exception];
    return YES;
}
 
- (void)printStackTrace:(NSException *)e
{
    NSString *stack = [[e userInfo] objectForKey:NSStackTraceKey];
    if (stack) {
        NSTask *ls = [[NSTask alloc] init];
        NSString *pid = [[NSNumber numberWithInt:[[NSProcessInfo processInfo] processIdentifier]] stringValue];
        NSMutableArray *args = [NSMutableArray arrayWithCapacity:20];
 
        [args addObject:@"-p"];
        [args addObject:pid];
        [args addObjectsFromArray:[stack componentsSeparatedByString:@"  "]];
        // Note: function addresses are separated by double spaces, not a single space.
 
        [ls setLaunchPath:@"/usr/bin/atos"];
        [ls setArguments:args];
        [ls launch];
        [ls release];
 
    } else {
        NSLog(@"No stack trace available.");
    }
}

В этом примере делегат вызывает printStackTrace: метод в его реализации exceptionHandler:shouldLogException:mask:; в этой точке исключение обрабатывается, но еще не вызвало завершение отлаженной исполнимой программы. Вывод atos утилита, когда объединено с NSExceptionHandler информация о журнале, взгляды, подобные Перечислению 2.

  Содержание перечисления 2 NSExceptionHandler регистрирует плюс atos вывод

2006-08-21 12:18:19.727 ExceptionHandleTest[916] NSExceptionHandler has recorded the following exception:
NSInvalidArgumentException -- *** -[NSCFString count]: selector not recognized [self = 0x2a00c]
Stack trace:  0x9275c27b  0x92782fd7  0x9280b0be  0x9272f207  0x90a51ba1  0x0002995f  0x00023f81  0x00001ca6  0x00001bcd  0x00000001
__NSRaiseError (in Foundation)
+[NSException raise:format:] (in Foundation)
-[NSObject doesNotRecognizeSelector:] (in Foundation)
-[NSObject(NSForwardInvocation) forward::] (in Foundation)
__objc_msgForward (in libobjc.A.dylib)
-[ExceptionTest testException] (in ExceptionHandleTest) (ExceptionTest.m:31)
_main (in ExceptionHandleTest) (ExceptionHandleTest.m:10)
start (in ExceptionHandleTest)
start (in ExceptionHandleTest)
0x00000001 (in ExceptionHandleTest)

Существуют другие способы выполнить тот же результат. Например, метод, распечатывающий символьное отслеживание стека, мог быть на категории, добавленной к NSException вместо метода класса делегата.