Xcode的“构建和分析”的范围是否会被认为是有限的泄漏?

时间:2010-04-29 16:09:44

标签: objective-c xcode memory-leaks clang clang-static-analyzer

它并不关心这个:

NSString* leaker()
{
 return [[NSString alloc] init];
}

我认为检查是否有任何代码路径可以调用该函数而不释放其返回值(我通常不会这样编码,我只是测试分析器)。

它将此报告为泄漏:

NSString* leaker()
{
 NSString* s = [[NSString alloc] init];
 [s retain];
 return s;
}

但不是这样:

NSString* leaker()
{
 NSString* s = [[NSString alloc] init];
// [s retain];
 return s;
}

对我来说似乎特别弱。它只在当地范围内进行分析吗?如果该工具无法接受这样的事情,我怎么能指望它能够发现我可能犯的实际错误呢?

1 个答案:

答案 0 :(得分:4)

clang不会执行任何过程间分析,至少现在还没有。即使它确实如此,它也可能不一定能够捕获这个“错误” - 潜在代码路径的排列趋向于以指数方式上升,使其成为一种实际的不可能性。

clang使用一组“大部分时间都有效”的启发式方法。值得庆幸的是,Cocoa内存管理规则往往相当统一,因此启发式方法适用于大多数用途。您给出的具体示例并未真正涵盖在内存管理规则中,但我认为大多数人(包括我自己)都倾向于将您的示例归类为“您通过API记录了{{{ 1}}负责leaker()返回的对象“。这基本上类似于release样式方法。

- (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. }