为什么CFRelease(NULL)会崩溃?

时间:2009-07-16 03:06:33

标签: objective-c core-foundation

CFRelease没有检查NULL的原因吗?当[nil release]时,这不是不可接受的;自由(NULL);删除NULL;一切都很好吗?

4 个答案:

答案 0 :(得分:29)

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的相似 - CF设计师认为传递NULL是一个编程错误。

答案 1 :(得分:9)

好的一点,乍一看似乎没什么意义。当然,behavior is properly documented,但如果它可以优雅地处理NULL会很好。请注意,CFRetainCFMakeCollectable(10.4中的新内容,10.5中启用的GC)表现出相同的行为。我并不知道以这种方式设计它的所有动机,但重点可能更多地放在与CoreFoundation框架其余部分的内部一致性上。

很难/不可能知道为什么 CF是这样设计的,除非你可以问其中一位设计师。我最好的猜测是设计者决定为内存管理函数传递NULL(应该是?)编程错误。有人可能会争辩说,导致NULL崩溃是一种理想的“快速失败”行为,因为几乎立即崩溃的错误比错误更容易追踪,而这些错误无声无息,而不是你期望的。就个人而言,我更喜欢无所事事的做法,但我猜这就是生活......

鉴于API不能/不会改变,您可以测试NULL或解决问题的情况。一个选项可能是定义一个内联函数或宏,它只为非NULL引用调用CFRelease。在任何情况下,最好在您的代码中明确,以避免混乱。

答案 2 :(得分:7)

所有这些功能都是不同API的一部分,遵循处理NULL的不同约定:

  1. CFRelease是CoreFoundation C SDK的一部分,默认情况下不接受NULL引用作为参数。
  2. [nil release]使用Objective-C(允许解除引用nil
  3. free(NULL)是C库(libc)的一部分,允许NULL参数
  4. delete NULL是允许libc++参数的C ++库(NULL)的一部分
  5. 我想CoreFoundation SDK编写者决定与SDK的其余部分更加一致,而不是在其他SDK中使用类似的功能。

答案 3 :(得分:2)

您可以查看CFReleaseProtector的源代码,以了解(或更好地理解)此问题。

CF发布不再对NULL进行崩溃,

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

您可以使用unar命令行工具解压缩CFReleaseProtector.sit(Unarchiver的一部分;请参阅其Google代码下载列表)。