这段代码是否泄漏?

时间:2011-01-27 21:51:24

标签: objective-c cocoa-touch

我刚刚通过仪器泄漏运行我的应用程序,我被告知以下代码会导致泄漏,但我不知道如何。

我使用以下代码在NSMutableArray中分配了一些viewDidLoad

- (void)viewDidLoad {
    [super viewDidLoad];
    self.currentCars = [[NSMutableArray alloc] init];
    self.expiredCars = [[NSMutableArray alloc] init];
}

然后我使用以下内容在我的viewWillAppear方法中填充这些数组:

[self.currentCars removeAllObjects];
[self.expiredCars removeAllObjects];
for (Car *car in [self.dealership cars]) {
    if ([car isCurrent])
        [self.currentCars addObject:car];

    if ([car isExpired])
        [self.expiredCars addObject:car];
}

稍后在代码中我将在这里发布这些数组:

- (void) viewWillDisappear:(BOOL)animated {

    if (currentCars != nil) {
        [currentCars release], currentCars = nil;
    }
    if (expiredCars != nil) {
        [expiredCars release], expiredCars = nil;
    }

    [super viewWillDisappear:animated];
}

有什么想法吗?谢谢!

3 个答案:

答案 0 :(得分:2)

问题是(可能)您在-viewDidLoad中使用属性访问器进行数组的初始设置。由于良好实现的属性访问器将保留该对象,因此您将从+ alloc获得1个保留,而另一个保留来分配它。要解决此问题,您应该在分配数组后释放它们,或者使用[NSMutableArray array]来获取用于初始分配的自动释放数组。

答案 1 :(得分:2)

你的泄漏在这里:

self.currentCars = [[NSMutableArray alloc] init];
self.expiredCars = [[NSMutableArray alloc] init];

假设你声明了这样的属性访问:

@property(nonatomic, retain) NSMutableArray *currentCars;
@property(nonatomic, retain) NSMutableArray *expiredCars;

在我看来,找到泄漏的最佳方法(使用仪器除外)是手动跟踪保留计数。

如果您使用例如currentCars进行此操作,则会轻易发现泄漏。以下是发生的事情:

self.currentCars = [[NSMutableArray alloc] init];
// The 'init' makes the retain count 1. 

// 'self.currentCars = ..' translates to the setCurrentCars: method.
// You probably did not implement that method yourself,
// but by synthesizing your property it is automatically implemented like this:
- (void)setCurrentCars:(NSMutableArray *)array {
    [array retain]; // Makes the retain count 2
    [currentCars release]; 
    currentCars = array;
}

// In your viewWillDisappear: method
[currentCars release], currentCars = nil; // Makes the retain count 1 so the object is leaked.

解决方案很简单。使用此:

NSMutableArray *tempMutableArray = [[NSMutableArray alloc] init];
self.currentCars = tempMutableArray;
[tempMutableArray release];

一个小小的旁注。您不应该在viewWillDisappear:中发布您的对象。推荐的地方是dealloc。所以你的代码是:

- (void)dealloc {
    [currentCars release], currentCars = nil;
    [expiredCars release], expiredCars = nil;
    [super dealloc];
}

答案 2 :(得分:0)

除非你在currentCarsexpiredCarsdealershipcars做一些非常奇怪的事情,否则,那里没有泄漏。

仪器指向泄漏位置的指针不一定是物体实际泄漏的地方。如果我猜测,我会说你可能忽略了在你的dealloc方法中释放currentCarsexpiredCars