Есть ли способ перехватить сообщения, отправленные на ноль в Objective-C? - PullRequest
11 голосов
/ 27 мая 2009

Меня только что укусила раздражающая ошибка , которая стала неясной из-за поведения "отправить сообщение в nil is ok" в Objective-C.

Я видел Отправка сообщения на ноль? , и консенсус в Objective-C выглядит так: «Вот как мы катимся».

Теперь, может быть, у меня недостаточно опыта в Objective-C, но кажется, что это было бы полезно заманить в ловушку, потому что я не могу придумать вескую причину, почему это должно происходить 1010 * того времени. Тем не менее, это может быть просто идиома кодирования, к которой я еще не привык.

Так что кроме проверки на ноль везде, вот так:

assert( object != nil );
[object message];

Есть ли способ заставить ловушку выполнить это условие и предупредить, когда object равен нулю?

Ответы [ 2 ]

9 голосов
/ 27 мая 2009

Вы можете использовать недокументированный трюк ObjC или dtrace (см. Комментарии к решению dtrace).

pid$1::objc_msgSend:entry
/arg0==0/
{
  ustack();
}
4 голосов
/ 27 мая 2009

ноль сообщений очень часто используется в ObjC. Люди могут бороться, хорошо это или плохо; к этому нужно привыкнуть. Если вы попытаетесь разбить его хитростями, то вы сломаете Какао, потому что Какао использует его. Существуют некоторые приемы (например, сообщение diciu), которые позволяют отлаживать в ситуациях, когда вы подозреваете, что нет сообщений, но просто не можете их найти. Но вы не можете просто оставить их в своем коде (и пост в блоге выше проясняет это). Обмен сообщениями ноль слишком распространен внутри фреймворков.

Впрочем, к исходной точке зрения сравните:

- (void)doSomethingWith:(id)x {
    NSAssert(x != nil, @"Don't pass me nil");
    [x something];
}

против

void Bar::DoSomething(Foo *x) {
    assert(x != NULL);
    if (x != NULL) {
       x.something;
    }
}

В обоих случаях вам нужно протестировать, и в обоих случаях компилятор не предупредит вас, если вы не сможете протестировать. Разница лишь в том, в каких случаях вы терпите крах / утверждаете. Лично я пишу макросы вокруг NSAssert(), которые заставляют его всегда печатать сообщение журнала в случае сбоя. Это только сбой в Debug. Таким образом, когда клиент отправляет мне логи, я вижу, что утверждения не сработали.

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