【问题标题】:memory leak when adding objects to nsarray向 nsarray 添加对象时发生内存泄漏
【发布时间】:2010-11-22 00:27:58
【问题描述】:

在下面的代码中,PersonListArray 是一个 NSMutableArray,我从 sqlite DB 获取人员列表并将其添加到我的数组中。

Person* tmpPerson = [[Person alloc] init];
tmpPerson.personName = @"Mike";
tmpPerson.personEmail = @"mike@mike.com"; 

[PersonListArray addObject:tmpPerson];
[tmpPerson release];

即使我在这里释放 Person 对象,它也会造成内存泄漏,我猜这是由于数组持有对它的引用计数。我在程序的其他地方使用了数组,然后确定释放它。

为数组创建新对象而不遇到此问题的最佳做法是什么?

在我释放数组的dealloc方法中

-(void) dealloc{
  [PersonListArray release]; // this contains the numerous Person objects
  [super dealloc];
}

我应该像这样手动释放它们吗?

-(void) dealloc{

   for (int i = 0; i<PersonListArray.count;i++)
   {
     Person * tmpPerson = [PersonListArray objectAtIndex:i];
     [tmpPerson release];
   }

  [PersonListArray release];
  [super dealloc];
}

【问题讨论】:

  • 这里有更多的代码来获得更好的图片... @interface Person : NSObject { NSString* personName; NSString* 个人移动; NSString* 个人邮箱; } @property (nonatomic, 保留) NSString* personName, *personEmail, *personMobile;

标签: iphone memory-leaks


【解决方案1】:

您向我们展示的代码是正确的,并且没有泄漏。不过,最后一部分是错误的,并且会导致您的程序崩溃,因为您正在释放您不再拥有的 Person 对象。

【讨论】:

  • 现在,如果我尝试将 Person 对象转换为字符串列表并将其添加到它可以工作的数组中,并且我不会在仪器中发现任何泄漏。但是现在我必须在从数组中访问对象时将每个对象转换为字符串,反之亦然。
【解决方案2】:

您的代码在最初实现时是正确的。数组保留添加到其中的对象,并在将它们从数组中删除或释放数组时释放它们。无需自己遍历数组。

您使用什么方法来检测泄漏?如果它是 Instruments,那么您可能会误解它告诉您的内容。当它检测到泄漏时,它可以向您显示首次分配内存的位置。它不能告诉你哪个对象对泄漏负责。因此,我猜测给定的 dealloc 方法永远不会被调用(因为该对象已泄漏),或者其他人保留了该数组并且不释放它。尝试将 NSLog 放入 dealloc 以确保它正在发生;作为一次运行一次的测试,您可以在释放 PersonListArray 后尝试记录它——如果这不会导致内存异常,那么几乎可以肯定其他人已经保留了它。

[已移除:我的原文“尝试将 [PersonListArray retainCount] 的 NSLog 添加到您的 dealloc 以确定是哪种情况。”;请参阅下面 bbum 的评论]

意外附加保留的最常见原因是@property/@sythesize 属性设置为保留但未将匹配的释放添加到dealloc。

【讨论】:

  • 我正在使用仪器,它在设备上的行为相同。仍然调用 dealloc 方法。如果我使用上面提到的对象 字符串转换方法,泄漏就会消失。这真的很奇怪
  • 您是否可能忽略了在 Person 的 dealloc 中释放 personName、personMobile 和 personEmail?
  • 请勿将 retainCount 用于调试目的。对象的绝对保留计数是一个实现细节,可能不是您所期望的,但仍能正常运行。
  • 谢谢;评论已修复。如果您可以将其用于相对目的,大概您可以将 dealloc 中的值与 alloc/init 之后的值进行比较?
  • retainCount 实际上非常偶尔有助于了解正在发生的事情。您只需要注意在任何给定时间都可能拥有很多东西(自动释放池、执行选择器和 NSInvocations 是不太明显的)。它在生产代码中没有用,但它有时对调试很有用。
【解决方案3】:

在您的应用程序的其他地方,您可能会调用[PersonListArray objectAtIndex:n] 并将其传递给您应用程序的其他各个部分。您的应用程序的其他部分之一可能正在泄漏它。

如果您使用泄漏,请单击特定的“泄漏类型”,然后单击内存地址,它会显示该内存地址的分配/释放/保留/释放/自动释放历史记录。如果您启用详细视图(我认为是 Cmd-E),您也会看到所有这些的堆栈跟踪。寻找一些正在保留但没有相应发布的东西。 (当事物被多个自动释放的数组保留时,这有点困难......)

【讨论】:

    猜你喜欢
    • 2016-01-26
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 2015-03-08
    • 2011-10-13
    • 1970-01-01
    • 1970-01-01
    • 2011-02-12
    相关资源
    最近更新 更多