下面的两种方法都分配一个 NSString 并泄漏它。运行 XCode (4.6) Analyzer 成功标记了 bar2 中的泄漏,但没有在 bar1 中提及它。
我不明白为什么。
在我的实际项目中,我们发现了一个泄漏,我们希望像 bar2 中那样以明显的方式捕获它,但由于 bar1 中的相同行为而没有找到。
请帮我理解为什么。谢谢!
-(void)bar1
{
NSString* foo = [[NSString alloc] initWithString:@"foo"];
NSLog(@"%@", foo);
for (int i=0; i<4; i++) {
}
}
-(void)bar2
{
NSString* foo = [[NSString alloc] initWithString:@"foo"];
NSLog(@"%@", foo);
}
你们中的一些人提到静态字符串大小写“过度设计”。这个不那么做作的示例显示了相同的行为:
-(void)bar1
{
NSString* foo = [[NSString alloc] initWithFormat:@"%d",rand()];
NSLog(@"%@", foo);
for (int i=0; i<4; i++) {
}
}
-(void)bar2
{
NSString* foo = [[NSString alloc] initWithFormat:@"%d",rand()];
NSLog(@"%@", foo);
}
感谢那些指出迭代次数有影响的人。对于 3,它报告泄漏,对于 4,它不报告。这是一个没有死代码的新示例,只有迭代中的差异:
报告泄漏:
-(void)bar1
{
int i=0;
while (i<3) {
i++;
}
NSString* foo = [[NSString alloc] initWithFormat:@"%d",i];
NSLog(@"%@", foo);
}
不报告泄漏:
-(void)bar2
{
int i=0;
while (i<4) {
i++;
}
NSString* foo = [[NSString alloc] initWithFormat:@"%d",i];
NSLog(@"%@", foo);
}
我已经向 Apple 开具了 DTS 工单,因为在我看来,这个经过改进的示例清楚地表明这是 Analyzer 中的一个错误。
DTS 要求我用 https://bugreport.apple.com 打开它作为一个错误我已经做到了。这是问题 ID 13491388。
2013 年 3 月 29 日更新: Apple 报告说我的错误 13491388 是错误 11486907 的骗局。 但是,我无法打开或阅读有关错误 11486907 的任何信息,因此该信息完全没有用。
Apple 开发者支持失败 :-(
最佳答案
Clang 的静态分析器似乎是基于控制流的:报告总是“如果你遵循这个代码路径,这件坏事就会发生”。我最好的猜测是,这是 SA 的不同位之间的不良交互:
- 泄漏检测器可能只会在下一次写入变量或函数返回时才注意到泄漏。
- 循环的次数是有限制的(以避免搜索永远耗时)——检查两次迭代应该足以检测出大多数循环错误。
- 在达到迭代限制时,静态分析器“知道”它不会退出循环(因为
i
仍然小于 4),所以它放弃了。
我怀疑减少迭代次数会导致检测到泄漏。
如果优化器确定变量在 NSLog()
返回后已失效并将此信息用于SA.
您还可以调整它在报告问题时的保守程度(通过命令行选项,或直接从命令行运行 clang?),但如果不标记大量错误,这可能很难做到积极的一面。
静态分析也不能替代使用像 Leaks 这样的泄漏检查器。
关于ios - XCode (4.6) Analyzer - 为什么在一种情况下检测到泄漏而不在另一种情况下检测到泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15440658/