iPhone应用程序中的内存泄漏



我来自C背景,你们很多人都知道Objective-C是从C派生出来的。我假设内存管理概念是相似的。我收到有关潜在内存泄漏的警告,但奇怪的是我在alloc后释放对象。看看这个例子:

self.cardCellArray = [[NSMutableArray alloc] initWithCapacity:kTotalNumberOfCards];

在交易中:

- (void) dealloc
{
[super dealloc];
[self.cardCellArray removeAllObjects];
}

我收到的内存泄漏消息是:

Method returns an Objective-C object with a +1 retain count

Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1

谁能发现我在这里做错了什么?

我假设 cardCellArray 属性是一个拥有引用(即保留或复制(。

self.cardCellArray = [[NSMutableArray alloc] initWithCapacity:kTotalNumberOfCards];

这应该是:

self.cardCellArray = [[[NSMutableArray alloc] initWithCapacity:kTotalNumberOfCards] autorelease];

甚至:

cardCellArray = [[NSMutableArray alloc] initWithCapacity:kTotalNumberOfCards];

确保内存管理正确。

此外,dealloc 方法应该是:

- (void)dealloc
{
   [cardCellArray release];
   [super dealloc];
}

这假定 cardCellArray 属性的实例变量名为 cardCellArray。

您不是在释放数组,而只是清空它。另请注意,我将[super dealloc]调用移到最后一行,这是因为对象及其实例变量稍后在 dealloc 链中被完全释放,因此您将尝试访问释放的内存。

- (void) dealloc
{
   [cardCellArray release];
   [super dealloc];
}

另一件事:您正在使用 self.cardCellArray = ,根据 ivar 的@property的外观,您可能需要删除self.部分,因为它保留了对象(或者您必须稍后手动释放它(。 保留对象的@propertycopyretain

  1. 检查属性cardCellArrayretain还是copy。 如果是这样,则在调用 self.cardCellArray 时,设置为属性的对象cardCellArray保留计数增加 1。

  2. 使用 allocinit 创建对象(例如 initWithCapacity: (返回保留计数为 1 的对象,因为您在此处调用了 alloc 方法。

    在创建没有调用alloc的对象时,例如 [NSMutableArray arrayWithCapacity:] 将返回一个autorelease对象(它会在需要时自动将其保留计数减少 1(,您可以认为它具有保留计数 0。

  3. 在方法 dealloc 中,您应该调用 [self.cardCellArray release] ,这将自动删除数组保留的所有对象。

您的代码在此处生成一个保留计数-1 对象后


[[NSMutableArray alloc] initWithCapacity:kTotalNumberOfCards]

并且当您调用
时,此对象的保留计数变为 2

self.cardCellArray = xxx

但是在 dealloc 中,您没有减少 cardCellArray 的保留计数,然后发生了泄漏。

所以把你的代码改成

self.cardCellArray = [[[NSMutableArray alloc] initWithCapacity:kTotalNumberOfCards] autorelease];

自动释放将在需要时自动减少保留计数。

self.cardCellArray = [NSMutableArray arrayWithCapacity:kTotalNumberOfCards];

NSMutableArray *_array = [[NSMutableArray alloc] initWithCapacity:kTotalNumberOfCards];
self.cardCellArray = _array;
[_array release];

cardCellArray = [[NSMutableArray alloc] initWithCapacity:kTotalNumberOfCards];
//this helps because it doesn't call `[self setCardCellArray]` which generate +1 retain count.

最后,记得在 Dealloc 方法中也发布cardCellArray

是的,正如 JustSid 建议的那样,您将双重保留数组并且永远不会释放它。

虽然Objective-C堆管理源于C,但管理单个对象的方式完全不同。

你没有说属性cardCellArray是如何定义的,但大概它被定义为retained,这样,当你分配给self.cardCellArray时,你实际上是在执行方法setCardCellArray,并且该方法"保留"了对象。 但是由于您的alloc调用,它已被保留,因此现在它保留了两次。

然后,在dealloc方法中,您根本不release它。 您可以通过执行[cardCellArray release];或执行self.cardCellArray = nil;来释放对象。 两者都会释放它(但只有一次 - 你需要用双重保留来解决你的问题(。

您无需执行removeAllObjects调用。 当您release对象(并且保留计数变为零(时,将调用对象的dealloc方法,并执行适合于它引用的对象的版本。

(正如 Sid 建议的那样,最后做[super dealloc]电话。

(但是,当然,上面的一切都在ARC的窗外,在那里你可以担心一组全新的和不同的东西,你可能会搞砸。

最新更新