我的iPhone应用程序中的内存泄漏在哪里?

问题描述:

这是一个简单的应用程序,从我的资源文件夹获取30张图片,在viewDidLoad期间将它们放入NSMutableArray,然后根据加速度计数据更改图片。我有一个来自IB的UIImageView覆盖整个视图,当加速度计更新其信息时,它将uiimageview.image交换为差异图。作品约10秒钟,然后崩溃与此:我的iPhone应用程序中的内存泄漏在哪里?

Program received signal: “0”. 
Data Formatters temporarily unavailable, will re-try after a 'continue'. (Unknown error loading shared library "/Developer/usr/lib/libXcodeDebuggerSupport.dylib") 

在这里四处寻找后,它听起来就像是一个内存泄漏。以下是我正在使用的代码:

Interface: 
{ 
    UIAccelerometer *accel; 
    IBOutlet UIImageView *pic; 
    NSMutableArray *picArr; 
} 

Implementation: 

- (void)viewDidLoad 
{ 
[super viewDidLoad]; 

picArr = [[NSMutableArray alloc] init]; //array of pics to be used 
NSString *path = [[NSString alloc] init]; //dynamic path of images to save to array 

for (int i = 1; i <= 30; i++) 
{ 
    path = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"nativity_test_%i", i] ofType:@"jpg"]; 

    [picArr addObject:[[UIImage alloc] initWithContentsOfFile:path]]; 

} 

accel = [UIAccelerometer sharedAccelerometer]; 
accel.delegate = self; 
accel.updateInterval = 0.5f; 

[path release]; 

pic.image = [picArr objectAtIndex:15]; 
} 

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration 
{ 

if(acceleration.y < 0.0f) //goes thru the tilted left pics 
{ 
    for (int i = 0; i <= 15; i++) 
    {      
     if(acceleration.y >= (-(15.0f-(double)i)/30.0f) && acceleration.y < (-(14.0f-(double)i)/30.0f)) 
     { 
      pic.image = [picArr objectAtIndex:i+1]; 
     } 
    } 
} 

else if(acceleration.y > 0.0f) //goes thru tilted right pics 
{  
    for (int i = 1; i <= 14; i++) 
     if(acceleration.y > ((double)i/30.0f) && acceleration.y <= ((double)(i+1)/30.0f)) 
     { 
      pic.image = [picArr objectAtIndex:i+15]; 
     } 
} 
} 

如果我遗漏了任何相关信息,请让我知道。

+0

实例变量是不是属性有关系吗? – Marty 2010-11-08 23:15:07

这不是由内存泄漏引起的崩溃,而是由内存过度释放造成的。你的崩溃是由这一行造成的:

[path release]; 

删除了这一行,你应该罚款。对于一些罚款的价值,无论如何;乔治所说的大部分内容也适用。

的原因是,被释放的路径将是这一个:

path = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"nativity_test_%i", i] ofType:@"jpg"]; 

这是一个对象为零的有效保留计数。虽然它有一个积极的保留计数,但它已经被自动释放,并且在您返回到主事件循环时将被释放。

你也应该删除此行:

NSString *path = [[NSString alloc] init]; //dynamic path of images to save to array 

的原因是你使用它分配pathForResource的结果路径,实际上从未。当然,您需要声明路径作为变量。我建议将pathForResource行更改为:

NSString *path = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"nativity_test_%i", i] ofType:@"jpg"]; 

这是一个明智的改变,因为在循环之外没有理由需要这个。

你也应该解决这一行:

[picArr addObject:[[UIImage alloc] initWithContentsOfFile:path]]; 

[UIImage的页头]以1为有效保留计数它添加到一个数组将增加两个返回的UIImage。如果您稍后才发布阵列,则会导致内存泄漏。相反:

[picArr addObject:[[[UIImage alloc] initWithContentsOfFile:path]] autorelease]; 

这将意味着你添加的UIImage为0的有效保留计数的数组,这将其撞至1,使得数组对象的唯一所有者。之后阵列消失时,大部分图像也会消失。 (imageView也将拥有分配给它的任何一个)

不要因为这些东西而感到沮丧:有一天很快你会突然想到它,想知道为什么它会让你头痛。 :)

+0

嗯,我不再获得内存警告,但它仍然崩溃。做出你所说的所有改变。难住了。可能只是放入30个不同的图像视图,并显示/隐藏。马虎,是的。 – Marty 2010-11-08 22:45:12

+0

试着打开NSZombieEnabled,它应该可以帮助你找到它。我认为这是正确的方法,它应该是可以修复的。 – 2010-11-08 22:59:59

+0

由于某种原因,它可以在第三代iPod上正常工作,但不是我的iPhone 3G。都运行4.1。任何想法为什么? – Marty 2010-11-10 23:55:05

有一对夫妇的问题在这里:

1)您还没有释放的UIImage对象您要添加到“picArr”。

这条线:

[picArr addObject:[[UIImage alloc] initWithContentsOfFile:path]]; 

应该是这样的,而不是:

UIImage *image = [[UIImage alloc] initWithContentsOfFile:path]; 
[picArr addObject: image]; 
[image release]; 

我相信你也可以这样做:

[picArr addObject: [[[UIImage alloc] initWithContentsOfFile:path] autorelease]]; 

2)你不需要做NSString * path = [[NSString alloc] init];你可以这样做: NSString * path; 您正在给第一个循环内的路径变量赋值,所以不需要alloc + init。一旦你改变这一点,你可以摆脱这行:

[path release]; 

3)我不知道你在哪里释放“picArr”本身,你需要。你可能已经在做,但没有在你的文章中包含这一点代码。

+0

我实际上已经与 [picArr addObject:[UIImage imageWithContentsOfFile:path]]; 但也没有工作。我尝试了你所说的也没有奏效。 picArr在dealloc中获得释放,但是我将它用于程序的生命周期,所以我不想在执行期间释放它。任何其他想法? – Marty 2010-11-08 22:13:23

+0

[picArr addObject:[UIImage imageWithContentsOfFile:path]]应该没问题。我相信[路径发布];线路会导致问题。在我提供的答案中尝试我的#2 ...只需使用NSString *路径;并停止释放“路径” – George 2010-11-08 22:17:51

+0

我得到内存警告1和2之前,它也崩溃了。我认为它不在viewDidLoad中,因为它使它很好,直到它将足够的图片换掉。我跑了仪器(第一次使用它),似乎每次图片改变更多的记忆被采取。我以为 pic.image = [picArr objectAtIndex:i + 1] 刚刚告诉图片属性在“pic”指向数组中的图像对象。我不知道。 – Marty 2010-11-08 22:18:40