我来自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.
部分,因为它保留了对象(或者您必须稍后手动释放它(。 保留对象的@property
是copy
和retain
-
检查属性
cardCellArray
是retain
还是copy
。 如果是这样,则在调用self.cardCellArray
时,设置为属性的对象cardCellArray
保留计数增加 1。 -
使用
alloc
和init
创建对象(例如initWithCapacity:
(返回保留计数为 1 的对象,因为您在此处调用了alloc
方法。
在创建没有调用alloc
的对象时,例如[NSMutableArray arrayWithCapacity:]
将返回一个autorelease
对象(它会在需要时自动将其保留计数减少 1(,您可以认为它具有保留计数 0。 -
在方法
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的窗外,在那里你可以担心一组全新的和不同的东西,你可能会搞砸。