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重复调用会泄漏实例。当它的名字暗示它不会时创建一个具有 +1 保留计数的实例。先前分配给实例变量的实例被泄露,因为它从未被释放。NSArraybarNSArrayarray

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

4

1 回答 1

5

无弧:

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

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

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

关于弧

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

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

所以如果可以的话,我建议转向 ARC。

于 2012-12-09T22:22:59.227 回答