Что такое «ловушка прерывания» и как мне ее отладить? - PullRequest
7 голосов
/ 10 января 2009

Я получаю это сообщение каждый раз, когда компилирую свой проект:

RunIPhoneUnitTest.sh: line 92: 31389 Abort trap              "$TARGET_BUILD_DIR/$EXECUTABLE_PATH" -RegisterForSystemEvents

Я понимаю, что проблема в моем коде, но тогда я не понимаю, как ее решить или найти.

Странно то, что я получаю это с помощью этого звонка:

-- This is the interface
@interface DbObject : NSObject {
    NSInteger Id;
    NSDate* timeStamp;
}

@property (nonatomic) NSInteger Id;
@property (nonatomic, retain) NSDate *timeStamp;
----
This fail with above error
----
NSString * filter = [NSString stringWithFormat:"id = %@", ds.Id, nil];

НО странно то, что я удаляю эту строку, этот метод и все равно получаю его! Схожу с ума.

В настоящее время я думаю об удалении кода, пока не получу сообщение об ошибке и не начну добавлять его, но думаю, существует ли более прагматичное решение ...

1 Ответ

11 голосов
/ 10 января 2009

Ловушка прерывания обычно означает, что прерывание вызвано где-то. Скорее всего, это происходит потому, что код вашего модульного теста вызывает исключение, которого он не ожидает, и просто обрабатывает это, вызывая abort (3). Вызов abort не очень прост для отладки, потому что он не предоставляет информации о том, кто его вызвал и почему, никогда не возвращается и не генерирует SIGABRT. Вы можете установить новый обработчик для SIGABRT и поместить точку останова тут же, а затем, по крайней мере, проверить текущий стек вызовов ... но прочитайте остальное для получения информации о том, почему это происходит в первую очередь.

Однако проблема с вашим кодом выше в том, что NSInteger не тип объекта, а обычный примитив. Чтобы исправить вашу ошибку, замените ошибочную строку следующим:

NSString *filter = [NSString stringWithFormat:@"id = %lld", (long long)ds.Id];

Во-первых, stringWithFormat принимает объект NSString в качестве параметра, поэтому вам нужно использовать символ '@', чтобы указать, что строковый литерал является строкой NSString. Это очень важно, поскольку @"blah blah" фактически переводится в объект. Вызов, который вы делаете для stringWithFormat, ожидает, что информация об объекте NSString будет находиться по этому адресу памяти, но вместо этого он получает строку символов и, скорее всего, взрывается там. Убедитесь, что все ваши строковые литералы имеют @"blah blah", где ожидается тип NSString, и что они не являются простыми c-строками.

Во-вторых, символ '@' в строке формата указывает объект. Поскольку NSInteger не является объектом, вы не можете использовать этот символ формата. Вместо этого используйте% lld для указания длинного целого числа. Наконец, вам не нужно добавлять nil в конец списка параметров при использовании stringWithFormat, так как сама строка формата определяет, сколько параметров ожидать.

Кроме того, причина, по которой %lld используется вместо просто %d, заключается в том, что NSInteger меняет размер в зависимости от того, собираете ли вы 32-битную или 64-битную цель. Повышая NSInteger до типа long long и используя спецификатор %lld, вы гарантируете, что у вас не будет проблем с усечением в будущем, если вы скомпилируете для 64-битной системы, а для значения NSInteger потребуется более 32 бит для хранения.

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