Есть ли причина, по которой CFRelease не проверяет наличие NULL? Разве это неприемлемо, когда [nil release]; бесплатно (NULL); удалить NULL; все работает отлично?
Почему CFRelease (NULL) сбой?
Ответ 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).