将对象添加到nsarray时发生内存泄漏

问题描述:

在下面的代码中,PersonListArray是一个NSMutableArray,我从sqlite数据库中获取人员列表并将其添加到我的数组中。将对象添加到nsarray时发生内存泄漏

Person* tmpPerson = [[Person alloc] init]; 
tmpPerson.personName = @"Mike"; 
tmpPerson.personEmail = @"[email protected]"; 

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

即使我在这里释放Person对象,它给我一个内存泄漏,我猜是由于数组持有引用计数。我在程序中的其他地方使用数组,然后肯定释放它。

为阵列创建新对象并且不会遇到此问题的最佳做法是什么?

在dealloc方法,其中i释放阵列

-(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]; 
} 
+0

这里有一些更多的代码来获得更好的图片... @interface Person:NSObject { \t NSString * personName; \t NSString * personMobile; \t NSString * personEmail; \t } @property(nonatomic,retain)NSString * personName,* personEmail,* personMobile; – ArdenDev 2010-11-22 09:52:56

您的代码,如最初实施的那样是正确的。一个数组会保留添加到它的onjects,并在它们从数组中移除或数组被处理时释放它们。不需要自己通过阵列。

你用什么手段检测泄漏?如果是乐器,那么你可能会误解它告诉你什么。当它检测到泄漏时,它可以显示内存首次分配的位置。它不能告诉你哪个物体对泄漏负责。因此,我会猜想给定的dealloc方法从来没有被调用过(因为该对象被泄露),或者其他人保留了该数组并且没有释放它。尝试把NSLog放在dealloc中以确保它正在发生;作为一次运行测试,您可以在释放它之后尝试记录PersonListArray - 如果这不会导致内存异常,那么几乎肯定有其他人保留它。

[删除:我的原始文本]尝试添加一个[PersonListArray retainCount]的NSLog到你的dealloc中,找出是哪种情况。请参阅下面的bbum的评论]

意外额外保留的最常见原因是@ property/@ sythesize属性,它们被设置为保留,但未将匹配版本添加到dealloc。

+0

我正在使用仪器及其在设备上的相同行为。 dealloc方法仍然被调用。如果我使用上面提到的对象字符串转换方法,则泄漏消失。这真的很奇怪 – ArdenDev 2010-11-22 06:20:37

+0

有没有可能你忽略在Person的dealloc中释放personName,personMobile和personEmail? – Tommy 2010-11-22 10:33:36

+1

**请勿将retainCount用于调试目的**。对象的绝对保留数是一个实现细节,可能不是您所期望的,同时仍然正确运行。 – bbum 2010-11-22 18:47:53

您向我们展示的代码是正确的,不包含任何泄漏。但最后一部分是错误的,并且会让你的程序崩溃,因为你正在释放你不再拥有的Person对象。

+0

因此,如果我尝试将Person对象转换为字符串列表并将其添加到数组中,它就会工作,并且我不会在工具中发现任何泄漏。但是现在我必须在从数组访问对象时将每个对象转换为字符串,反之亦然。 – ArdenDev 2010-11-22 06:17:44

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

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