CFRelease没有检查NULL的原因吗?当[nil release]时,这不是不可接受的;自由(NULL);删除NULL;一切都很好吗?
答案 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
会很好。请注意,CFRetain
和CFMakeCollectable
(10.4中的新内容,10.5中启用的GC)表现出相同的行为。我并不知道以这种方式设计它的所有动机,但重点可能更多地放在与CoreFoundation框架其余部分的内部一致性上。
很难/不可能知道为什么 CF是这样设计的,除非你可以问其中一位设计师。我最好的猜测是设计者决定为内存管理函数传递NULL(应该是?)编程错误。有人可能会争辩说,导致NULL崩溃是一种理想的“快速失败”行为,因为几乎立即崩溃的错误比错误更容易追踪,而这些错误无声无息,而不是你期望的。就个人而言,我更喜欢无所事事的做法,但我猜这就是生活......
鉴于API不能/不会改变,您可以测试NULL或解决问题的情况。一个选项可能是定义一个内联函数或宏,它只为非NULL引用调用CFRelease。在任何情况下,最好在您的代码中明确,以避免混乱。
答案 2 :(得分:7)
所有这些功能都是不同API的一部分,遵循处理NULL
的不同约定:
CFRelease
是CoreFoundation C SDK的一部分,默认情况下不接受NULL
引用作为参数。[nil release]
使用Objective-C(允许解除引用nil
)free(NULL)
是C库(libc
)的一部分,允许NULL
参数delete NULL
是允许libc++
参数的C ++库(NULL
)的一部分我想CoreFoundation
SDK编写者决定与SDK的其余部分更加一致,而不是在其他SDK中使用类似的功能。
答案 3 :(得分:2)
您可以查看CFReleaseProtector的源代码,以了解(或更好地理解)此问题。
CF发布不再对NULL进行崩溃,
http://unsanity.org/archives/haxies/cfrelease_no_mo.php
您可以使用unar命令行工具解压缩CFReleaseProtector.sit(Unarchiver的一部分;请参阅其Google代码下载列表)。