Есть ли способ перехватить сообщения, отправленные на ноль в Objective-C?

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

Я видел отправку сообщения на ноль? и консенсус, кажется, "вот как мы катимся" в Objective-C.

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

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

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

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

2 ответа

Решение

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

pid$1::objc_msgSend:entry
/arg0==0/
{
  ustack();
}

Обмен сообщениями ноль очень часто используется в 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. Таким образом, когда клиент отправляет мне логи, я вижу, что утверждения не удалось.

Другие вопросы по тегам