Почему assert просто завершает работу программы, скомпилированной для iPhone? - PullRequest
8 голосов
/ 04 января 2010

Я отлаживаю мощное приложение assert () для iPhone (Xcode, Objective-C ++ и симулятор устройства). В некоторых случаях ошибка assert просто завершает работу приложения, а не влечет за собой отладчик, как я ожидал.

Я сделал обходной путь, применив свое собственное любопытное утверждение с эффектом:

#define AssertLite(b) if(!(b)) {asm {int 3}}

(пух опущен), но мне интересно, сталкивался ли кто-нибудь с этим. Я не мог определить образец относительно того, когда это ломается и когда это заканчивается. Код не является многопоточным; все это делается в обработчиках событий.

Почему это происходит и как заставить vanilla assert () вести себя как условная точка останова?

Ответы [ 4 ]

15 голосов
/ 05 января 2010

Прежде всего, поскольку вы работаете над приложением для iPhone, вам, вероятно, следует использовать NSAssert () вместо функции vanilla BSD assert.

например. NSAssert(the_object, @"NIL object encountered");

Макрос NSAssert вызовет исключение Objective C (NSInternalInconsistencyException), если утверждение не выполнено.

Так как ваша цель - сломать исключение, следующий шаг - отключить отладчик XCode для исключений Objective-C. В любом случае, это, наверное, хорошая вещь.

В окне Точки останова (пункт меню Выполнить-> Показать-> Точки останова) щелкните там, где написано «Двойной щелчок для символа», чтобы ввести символ -[NSException raise]

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

Вот макрос, который я использую для компиляции утверждений в коде времени выполнения (обратите внимание, что затем я использую HMAssert в своем коде вместо NSAssert):

#ifdef DEBUG
#   define HMAssert(A,B) NSAssert(A,B)
#else
#   define HMAssert(A,B)
#endif

Для этого требуется определить макрос препроцессора DEBUG. Вот как это настроить:

  1. Щелкните правой кнопкой мыши по вашему проекту в Xcode. Это будет верхний элемент на левой панели, где перечислены файлы ваших проектов
  2. Выберите «Получить информацию» из всплывающего контекстного меню.
  3. Перейдите на вкладку «Сборка».
  4. Убедитесь, что для «Конфигурация» установлено значение «Отладка».
  5. Введите DEBUG в поле рядом с «Макросы препроцессора» в разделе «GCC 4.2 - Предварительная обработка».
4 голосов
/ 24 ноября 2010

Прежде всего, если вы добавите «Исключительную точку останова ...» в Навигаторе точек останова (⌘6), отладчик остановится на сбоях NSAssert, что позволит вам посмотреть на стек и понять, что пошло не так.

Вы должны использовать стандартную NSAssert. Если вы используете его правильно, вам не нужно много создавать вручную - все, что упомянул Майк, похоже на реализацию NSAssert по умолчанию.

Вам следует запустить конфигурацию релиза с NS_BLOCK_ASSERTIONS, установленным в предварительно скомпилированных заголовках (следуйте инструкциям Майка), чтобы отключить утверждения. Если вам нужна дополнительная информация о том, почему это сделать, проверьте: http://myok12.wordpress.com/2010/10/10/to-use-or-not-to-use-assertions/

0 голосов
/ 14 февраля 2013

Один раз я видел поведение, отличное от вызовов assert () один раз. Это было вызвано тем, что компилятор выбирал разные определения макросов на разных этапах процесса сборки.

Как только пути включения были выправлены, все они работали одинаково.

0 голосов
/ 23 апреля 2012

В Xcode 4 и новой iOS NSAssert может фактически принимать переменный список параметров. Это может быть полезно для регистрации некоторых значений вместе с assert. Утверждение компиляции (см. Ответ Майка выше) можно определить так:

#ifdef DEBUG
#   define DAssert(A, B, ...) NSAssert(A, B, ##__VA_ARGS__);
#else
#   define DAssert(...);
#endif

Кроме того, больше нет пункта меню Run → Show → Breakpoints. См. этот пост , чтобы настроить Xcode 4 для разрыва утверждения, как определено выше.

...