Подтвердить что ты не робот

Почему CFRelease (NULL) сбой?

Есть ли причина, по которой CFRelease не проверяет наличие NULL? Разве это неприемлемо, когда [nil release]; бесплатно (NULL); удалить NULL; все работает отлично?

4b9b3361

Ответ 1

Исходный код для CoreFoundation является общедоступным. В частности, для Snow Leopard код CFRelease находится в http://www.opensource.apple.com/source/CF/CF-550/CFRuntime.c

Вот как выглядит соответствующая часть:

void CFRelease(CFTypeRef cf) {
    if (NULL == cf) HALT;
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
    if (CF_IS_COLLECTABLE(cf)) {
        if (CFTYPE_IS_OBJC(cf)) {
            // release the GC-visible reference.
            auto_zone_release(auto_zone(), (void*)cf);
        } else {
            // special-case CF objects for better performance.
            _CFRelease(cf);
        }
        return;
    }
#endif
}

Это не отвечает на ваш вопрос о мотивации дизайна, но вы также спрашивали, почему CFRelease не проверяет NULL. Он проверяет и не выполняет цели, когда в качестве параметра передается NULL.

Моя личная убежденность похожа на Quinn's, что дизайнеры CF почувствовали, что ошибка программирования передается NULL.

Ответ 2

Хорошо, на первый взгляд это, похоже, не имеет особого смысла. Конечно, поведение правильно документировано, но было бы неплохо, если бы он мог обработать NULL изящно. Обратите внимание, что CFRetain и CFMakeCollectable (новые в 10.4, GC, включенные в 10.5) демонстрируют такое же поведение. Я не отношусь ко всем мотивациям для его проектирования таким образом, но акцент был, вероятно, больше на внутренней согласованности с остальной базой CoreFoundation.

Сложно/невозможно узнать , почему CF был разработан таким образом, если вы не можете спросить одного из дизайнеров. Мое лучшее предположение заключается в том, что дизайнеры решили, что передача NULL для функций управления памятью (должна быть?) Является ошибкой программирования. Можно утверждать, что причиной сбоя в NULL является желаемое "неудачное" поведение, так как ошибки, которые почти сразу же сбой, легче отследить, чем ошибки, которые молча делают ничего, а не то, что вы ожидаете. Лично я предпочитаю подход do-nothing-on-null, но я думаю, что жизнь...

Учитывая, что API не может/не измениться, вы можете либо протестировать NULL, либо решить проблему. Одним из вариантов может быть определение встроенной функции или макроса, который вызывает только CFRelease для ссылок, отличных от NULL. В любом случае, лучше всего быть явным в вашем коде, чтобы избежать путаницы в будущем.

Ответ 3

Все эти функции являются частью различных API, которые следуют различным соглашениям относительно обработки NULL:

  • CFRelease является частью SDK CoreFoundation C, который по умолчанию не принимает ссылку NULL как аргументы.
  • [nil release] использует Objective-C (который позволяет разыменовывать nil)
  • free(NULL) является частью библиотеки C (libc), которая позволяет NULL arguments
  • delete NULL является частью библиотеки С++ (libc++), которая позволяет NULL arguments

Я думаю, что авторы SDK CoreFoundation решили быть более совместимыми с остальной частью SDK, а не с аналогичной функцией в других SDK.

Ответ 4

Вы можете взглянуть на исходный код CFReleaseProtector, чтобы получить описание (или лучшее понимание) этой проблемы.

CFRelease больше не падает с NULL,

http://unsanity.org/archives/haxies/cfrelease_no_mo.php

Вы можете распаковать CFReleaseProtector.sit с помощью инструмента командной строки unar (часть The Unarchiver, см. его список загрузки кода Google).