Почему происходит сбой CFRelease (NULL)? - PullRequest
21 голосов
/ 16 июля 2009

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

Ответы [ 4 ]

30 голосов
/ 22 октября 2009

Исходный код для 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.

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

9 голосов
/ 16 июля 2009

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

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

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

7 голосов
/ 16 июля 2009

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

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

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

2 голосов
/ 17 февраля 2011

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

CFВыберите больше не сбой на NULL,

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

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

...