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