Управление ответом программы на исключения
Этот документ описывает некоторые пользовательские значения по умолчанию и API платформы Обработки исключений, которую можно использовать для управления поведением приложений в ответ на определенные типы ошибок.
Для использования служб платформы Обработки исключений в проекте Какао (или приложение или неприложение) добавить ExceptionHandling.framework
в /System/Library/Frameworks
к Вашему проекту XCode. Также вставьте следующую директиву импорта в заголовок или файл реализации класса, использующего платформу:
#import <ExceptionHandling/NSExceptionHandler.h> |
Ошибки приложения
Определенные типы ошибок приложения обычно заставляют приложения Какао выходить резко. Можно использовать пользовательское значение по умолчанию, NSExceptionHandlingMask
, управлять этим поведением (для Приложения только Основанные на наборе приложения) для трех из наиболее распространенных классов таких ошибок:
непойманный NSExceptions;
исключения системного уровня (такие как недопустимые доступы памяти)
Ошибки периода выполнения Objective C (такие как сообщения отправил к освобожденным объектам).
Для этих ошибочных типов можно установить NSExceptionHandlingMask
сделать одно из следующих действий:
Распечатайте дескриптивный журнал и отслеживание стека к консоли, когда произойдет такая ошибка.
Обработайте ошибку таким способом как для предотвращения получающегося резкого завершения,
Сделайте оба из вышеупомянутых.
Вы создаете маску путем добавления значений, соответствующих типам ошибок, которые будут зарегистрированы или обработаны:
Тип действия | Постоянный | Значение для |
---|---|---|
Зарегистрируйте непойманный NSExceptions | 1 | |
Обработайте непойманный NSExceptions | 2 | |
Исключения системного уровня журнала | 4 | |
Исключения системного уровня дескриптора | 8 | |
Зарегистрируйте ошибки периода выполнения | 16 | |
Обработайте ошибки периода выполнения | 32 |
Таким образом, если Вы вводите следование командной строки (в Терминальном приложении):
defaults write NSGlobalDomain NSExceptionHandlingMask 63 |
Вы вызываете журналирование и обработку поведения, описанного выше для всех неперехваченных исключений, исключений системного уровня и ошибок периода выполнения во всех приложениях.
Слово «дескриптор» в константах обработки исключений имеет определенное значение в зависимости от типа исключения. Платформа Обработки исключений обрабатывает исключения системного уровня и ошибки периода выполнения путем преобразования их в NSException
объекты. Эти объекты исключения содержат отслеживание стека в их userInfo
словарь под ключом NSStackTraceKey
. Непойманные дескрипторы платформы NSException
объекты путем завершения потока, в котором они происходят. Исключения на основном потоке приложения Какао пойманы обработчиками верхнего уровня, обычно устанавливающимися Набором Приложения.
Вместо NSExceptionHandlingMask
пользовательское значение по умолчанию, можно использовать setExceptionHandlingMask:
метод платформы Обработки исключений для получения того же поведения обработки исключений. И для приложения и для неприложения исполнимые программы Какао, соединитесь против платформы Обработки исключений и отправьте следующее сообщение:
[[NSExceptionHandler defaultExceptionHandler] setExceptionHandlingMask: aMask] |
aMask
параметр является небольшим количеством маски, составленной поразрядным осуществлением операции ИЛИ константы, перечисленные в таблице выше. Посмотрите заголовочные файлы платформы Обработки исключений для большего количества подробных данных о NSExceptionHandler API.
Отладка Средств
Для отладки целей также возможно использовать те же механизмы для создания отчетов относительно NSExceptions, который был бы иначе пойман. Можно также использовать любого NSExceptionHandlingMask
свойство defaults
система с этой целью или setExceptionHandlingMask:
метод класса NSExceptionHandler. Связанные константы и значения перечислены в следующей таблице:
Тип действия | Постоянный | Значение для |
---|---|---|
Исключения журнала, которые были бы пойманы обработчиками исключений верхнего уровня в NSApplication. Посмотрите примечание ниже. | 64 | |
Исключения дескриптора, которые были бы пойманы обработчиками исключений верхнего уровня в NSApplication |
| 128 |
Исключения журнала, которые будут пойманы на более низких уровнях | 256 | |
Исключения дескриптора, которые будут пойманы на более низких уровнях | 512 |
В этих случаях, обрабатывая исключение означает не что иное как добавляя отслеживание стека к userInfo
словарь под ключом NSStackTraceKey
. Обратите внимание на то, что перехваченные исключительные ситуации должны быть зарегистрированы или обработаны только для отладки, не при нормальных обстоятельствах, потому что выполнение так может генерировать большие суммы вывода или изменить нормальное поведение приложений.
В дальнейших целях отладки можно изменить поведение обработки для любого условия, обработанного NSExceptionHandler так, чтобы приложение было вместо этого остановлено так, отладчик может быть присоединен. Можно управлять этим поведением с суммированными значениями для NSExceptionHangingMask
пользовательское значение по умолчанию или с битовой маской, переданной в setExceptionHangingMask:
из класса NSExceptionHandler. В следующей таблице перечислены допустимые константы и defaults
значения:
Тип действия | Постоянный | Значение для |
---|---|---|
Зависните для неперехваченных исключений | 1 | |
Зависните для исключений системного уровня | 2 | |
Зависните для ошибок периода выполнения | 4 | |
Зависните для перехваченных исключительных ситуаций верхнего уровня | 8 | |
Зависните для других перехваченных исключительных ситуаций | 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
вместо метода класса делегата.