Xcode的“构建和分析”的作用范围是什么?
它不关心这个:Xcode的“构建和分析”的作用范围是什么?
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;
}
这似乎特别弱到我。它只在本地范围内进行分析吗?如果这个工具无法接受这样的事情,我怎么能期望它能够弥补我可能犯的实际错误?
clang
不执行任何程序间分析,至少不是。即使这样做了,它也未必会抓住这个“错误” - 潜在的代码路径的排列往往会呈指数级增长,使其变得实际上不可能。
clang
适用于“大部分时间”工作的一套启发式方法。值得庆幸的是,可可内存管理规则往往相当统一,所以启发式对大多数用途都有效。您提供的具体示例并未真正涵盖内存管理规则,但我认为大多数人(包括我自己)都倾向于将您的示例归类为“您通过API记录了leaker()
的调用者是负责返回的对象“。这基本上类似于- (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
。