为什么CFRelease(NULL)会崩溃?

Dav*_*Lin 21 objective-c core-foundation

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

sbo*_*oth 30

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
}
Run Code Online (Sandbox Code Playgroud)

这不能回答你关于设计动机的问题,但你也问过为什么CFRelease不检查NULL.当NULL作为参数传递时,它会检查并故意失败.

我的个人信仰与Quinn的相似 - CF设计者认为传递NULL是一个编程错误.


Qui*_*lor 9

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

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

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

  • 考虑到Quartz CGImageRelease和similars确实接受NULL:"此函数等同于CFRelease,但如果image参数为NULL则不会导致错误." (4认同)

not*_*oop 7

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

  1. CFRelease是CoreFoundation C SDK的一部分,NULL默认情况下不接受引用作为参数.
  2. [nil release]使用Objective-C(允许解引用nil)
  3. free(NULL)是C库(libc)的一部分,它允许NULL参数
  4. delete NULLlibc++允许NULL参数的C++库()的一部分

我想CoreFoundationSDK编写者决定与SDK的其余部分更加一致,而不是在其他SDK中使用类似的功能.

  • 您的"社区"似乎不包括Apple可能知道原因的开发人员. (3认同)
  • 对我来说,这个答案几乎说:CFRelease崩溃,因为CF以这种方式工作.free(NULL)不会崩溃,因为C标准这样说.删除NULL不会崩溃,因为C++标准这样说.它没有回答我的问题.我问为什么CF SDK设计师故意决定让他们的公共API崩溃程序. (2认同)