Xcode静态分析器无法检测泄漏?

3

我已经整理了下面这个最小化的例子,其中Xcode(4.5.2)静态分析器似乎没有检测到泄漏,以验证我对静态分析器的一些观察:

#import <Foundation/Foundation.h>

@interface Foo : NSObject {
    NSArray *array;
}
@property (nonatomic, retain) NSArray *array;
- (void)bar;
@end

@implementation Foo
@synthesize array;
- (void)bar
{
    // Shouldn't the static analyzer flag this as a leak?
    array = [[NSArray alloc] initWithObjects:@"hello", @"world", nil];
}
@end

int main(int argc, const char *argv[])
{
    @autoreleasepool {
        Foo *foo = [[Foo alloc] init];

        [foo bar];
        [foo bar];
        [foo bar];

        [foo release];
    }

    return 0;
}

重复调用bar会泄露NSArray实例,如果我没有搞错的话。 bar创建了一个+1保留计数的NSArray实例,而它的名称暗示着它不应该这样做。之前分配给array实例变量的实例泄漏了,因为它从未被释放。
然而,真正让我担心的是,我在某个地方读到 ARC 基本上使用与静态分析器相同的算法。这是否意味着这段代码在 ARC 下也会泄漏?或者即使没有__strong限定符或相应的(strong)属性,ARC 默认也将所有实例变量视为 strong?

1
是的,在 ARC(自动引用计数)下,所有实例变量(以及作用域内的局部变量)都被视为强引用类型变量。 - Mario
1个回答

5

没有弧:

它无法检测到泄漏,因为数组是实例变量。因此,将其分配给保留计数为1的对象不被视为泄漏,因为实例变量数组仍然是可访问且有效的。
即使您多次调用该方法,静态分析器也不足够聪明,无法知道数组指向一个已保留的变量。
静态分析器只能帮助您了解单个方法中对象何时泄漏。
但尝试以以下方式更改该方法:

- (void)bar
{
    // Shouldn't the static analyzer flag this as a leak?
    NSArray* array2 = [[NSArray alloc] initWithObjects:@"hello", @"world", nil];
}

这将被静态分析器检测到。

关于ARC

使用ARC时,此代码不会泄漏,因为当您说array=时,就像是:

  1. 释放数组:
  2. 保留新创建的对象;
  3. 将其分配给实例变量。

因此,如果可以,请转向ARC。


我明白了,谢谢!所以我不能依赖静态分析器来安全地检测我的Cocoa代码中的所有内存泄漏。更不用说Core Foundation相关的东西了... - tajmahal
仅针对简单的泄漏;此外,仪器无法检测到该泄漏,但我相信它们以后会改进,现在我们只能进行一些额外的调试。 - Ramy Al Zuhouri
1
静态检测所有的内存泄漏,在最一般的情况下,不幸地归结为停机问题。 - Catfish_Man

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接