0

我来自 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

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

4

4 回答 4

4

我假设 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。

于 2012-05-07T00:53:50.727 回答
3

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

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

另一件事:您正在使用self.cardCellArray =,这取决于您的@propertyfor ivar 的外观,您可能必须删除该self.部分,因为它保留了对象(或者您必须稍后手动释放它)。@property保留对象的是copyretain

于 2012-05-07T00:50:56.353 回答
1

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

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

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

然后,在dealloc方法中你根本不release这样做。[cardCellArray release];您可以通过doing或doing释放对象self.cardCellArray = nil;。要么释放它(但只有一次——你需要用双重保留来解决你的问题)。

无需removeAllObjects拨打电话。当您release创建一个对象(并且保留计数变为零)时,将dealloc调用该对象的方法并执行适合其引用的对象的释放。

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

(但当然,上面的一切都在 ARC 的窗口之外,在那里你会担心一系列全新的、不同的事情,你可能会搞砸。)

于 2012-05-07T01:16:49.397 回答
1
  1. 检查属性cardCellArrayretain还是copy。如果是这样,当您调用时self.cardCellArray,您设置为属性的对象cardCellArray获取保留计数增加1。

  2. alloc使用&创建对象init(例如initWithCapacity:)返回一个保留计数为 1 的对象,因为您在alloc这里调用了一个方法。

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

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

您的代码在此处生成一个 retain-count-1 对象

[[NSMutableArray alloc] initWithCapacity:kTotalNumberOfCards]

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

self.cardCellArray = xxx

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

所以将您的代码更改为

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

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.

cardCellArray最后,记得在 dealloc 方法中也释放

于 2012-05-07T02:26:02.833 回答