Почему этот вызов Objective C кажется зависшим? - PullRequest
6 голосов
/ 14 декабря 2011

Мой друг обнаружил странное поведение с NSDictionary, и мне интересно, почему это происходит.Рассмотрим следующий код:

NSDictionary *dict = [[NSDictionary alloc] init];

// Oops, we can't mutate an NSDictionary
[dict setObject:[[NSNull alloc] init] forKey:@"test"];
NSLog(@"Set");

Код выдает предупреждение при компиляции, что «NSDictionary» может не отвечать на «setObject: forKey:».Это все хорошо, и если вы все равно его запустите, вы получите такой вывод в консоли:

- [__NSCFDictionary setObject: forKey:]: метод мутирования, отправленный в неизменяемый объект

Опять же, именно то, что вы ожидаете.Однако в этот момент приложение не аварийно завершает работу и не завершает работу из-за необработанного исключения.Метод setObject: forKey: просто никогда не возвращается, и приложение, кажется, зависает;следующее NSLog никогда не выполняется.Если вы попытаетесь перейти к методу или использовать метод с использованием GDB, отладка, похоже, закончится, но без какого-либо явного сообщения об ошибке.Приложение продолжает работать, но отладчик не дает ни малейшего представления о том, где в коде «застряло» выполнение.

Что здесь происходит?Что на самом деле делает приложение в этом случае, и почему оно не аварийно завершает работу с NSInternalInconsistencyException или чем-то подобным?

Edit : для тех, кто спросил, я запускаюXCode 4.1 на OS X Lion (10.7.2), сборка с «компилятором Apple LLVM 2.1».Я использую все настройки по умолчанию, которые вы получаете с новым проектом Cocoa в XCode 4. Я испытываю одно и то же без сбоев, независимо от того, отлаживаю ли я программу или просто запускаю ее.Переход от сборки отладки к сборке выпуска не имеет значения.Я даже могу найти файл .app вручную в Finder и дважды щелкнуть по нему, чтобы запустить его вне XCode, и он все равно не падает.

1 Ответ

1 голос
/ 16 декабря 2011

Исключения не приводят к сбою программ AppKit. NSApplication устанавливает обработчик исключений по умолчанию, который перехватывает исключения, которых нет в вашем коде. Тогда вы просто возвращаетесь в runloop как обычно.

Многие приложения демонстрируют такое поведение. Это частая причина необъяснимых пустых представлений / окон. Если произойдет исключение до того, как представлению удастся завершить рисование, оно будет пустым, но приложение не будет аварийно завершено. Исключения вызывают сбой, только если вы намеренно изменили обработчик исключений по умолчанию на сбой.

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