Xcode静态分析仪没有检测到泄漏?

taj*_*hal 3 memory-leaks memory-management objective-c automatic-ref-counting

我把以下最小的例子放在一起,其中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;
}
Run Code Online (Sandbox Code Playgroud)

如果我没有弄错的话,bar反复调用会泄漏NSArray实例.当名称暗示它不会bar创建NSArray具有+1保留计数的实例.先前分配给array实例变量的实例将被泄露,因为它从未被释放.

然而,真正令我担忧的是,我在某处读到ARC基本上使用的算法与静态分析器相同.这是否意味着此代码也会在ARC下泄漏?或者,即使没有__strong限定符或相应的(strong)属性,ARC也会默认将所有实例变量视为强变量?

Ram*_*uri 5

没有弧形:

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

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

这将由静态分析器检测到.

关于ARC

使用ARC时,这段代码没有泄漏,因为当你说array =时,就像你:

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

所以如果可以,我建议转向ARC.