clang
不执行任何过程间分析,至少现在还没有。即使这样做了,它也不一定能捕捉到这个“错误”——潜在代码路径的排列往往会呈指数级上升,这使得它实际上是不可能的。
clang
使用一组“大部分时间”有效的启发式方法。值得庆幸的是,Cocoa 内存管理规则往往是相当统一的,因此启发式方法适用于大多数用途。您给出的具体示例并未真正包含在内存管理规则中,但我认为大多数人(包括我自己)倾向于将您的示例归类为“您已通过调用者leaker()
负责的 API 记录for release
ing 返回的对象”。这本质上类似于- (NSString *)init...
样式方法。
clang
知道以开头的方法init...
返回一个“未释放”对象,调用者有责任确保它被正确释放。这构成了启发式算法核心的一部分——它不需要整个程序或过程间分析来进行大量的引用计数检查——如果本地代码块通过init...
方法获取对象,则本地代码块需要以确保它是正确的released
。自然,如果本地代码块和所讨论的对象是init...
方法本身的一部分,则它被相同的“规则”覆盖,因此它会出现异常。
你可能想要的是这样的:
NSString* leaker() __attribute__((ns_returns_retained))
{
return [[NSString alloc] init];
}
这让分析器知道leaker()
返回一个“保留”对象,调用者负责正确释放它。虽然我没有对此进行测试,但我强烈怀疑会在leaker()
调用点检测到“泄漏”,即:
void test(void)
{
NSString *leaked = leaker();
// Previous line should be caught as a "leak" by clang.
}
这是任何静态分析器的不幸限制之一,而不仅仅是clang
.