【问题标题】:Where's the memory leak in my iPhone app?我的 iPhone 应用程序中的内存泄漏在哪里?
【发布时间】:2010-11-08 21:58:45
【问题描述】:

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

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];
        }
}
}

如果我遗漏了任何相关信息,请告诉我。

【问题讨论】:

  • 实例变量不是属性有关系吗?

标签: iphone memory-leaks ios


【解决方案1】:

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

[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 alloc] 返回一个有效保留计数为 1 的 UIImage。将其添加到数组中会将其增加到 2。如果你稍后才释放数组,这将导致内存泄漏。而是:

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

这意味着您要向数组添加一个有效保留计数为 0 的 UIImage,这会将其增加到 1,从而使数组成为对象的唯一所有者。稍后当阵列消失时,大多数图像也会消失。 (imageView 也将拥有分配给它的任何内容。)

不要对这些东西感到沮丧:有一天你会突然明白它为什么会让你头疼。 :)

【讨论】:

  • 好吧,我不再收到内存警告,但它仍然崩溃。做了你说的所有改变。难住了。可能只放入 30 个不同的 uiimageview,然后它们会显示/隐藏。马虎,是的。
  • 尝试开启 NSZombieEnabled,这应该可以帮助您找到它。我认为这是正确的方法,应该是可以修复的。
  • 好吧,由于某种原因,它在第三代 iPod 上运行良好,但在我的 iPhone 3G 上却不行。两者都运行 4.1。知道为什么吗?
  • 好吧,你的 iPhone 3G 的 RAM 将会减少。你的图片有多大?
  • 是的,我发现了,哈哈。没想到图片太大了,估计是。大约 440kb * 30 张图片 = 13.2 mb。没想到这么多……
【解决方案2】:

这里有几个问题:

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

这一行:

[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 release];

3) 我看不出你在哪里发布“picArr”本身,你需要。您可能已经这样做了,但没有在您的帖子中包含那段代码。

【讨论】:

  • 我实际上已经用 [picArr addObject:[UIImage imageWithContentsOfFile:path]];但这也没有用。我试过你说的也没有用。 picArr 在 dealloc 中释放,但我在程序的整个生命周期中都使用它,所以我不想在执行期间释放它。还有其他想法吗?
  • [picArr addObject:[UIImage imageWithContentsOfFile:path]] 应该没问题。我相信[路径释放];线会引起问题。在我提供的答案中尝试我的#2...只需使用 NSString *path;并停止释放“路径”
  • 我在崩溃之前收到内存警告 1 和 2。我认为它不在 viewDidLoad 中,因为它在交换足够多的图片之前会变得很好。我运行了 Instruments(第一次使用它),似乎每次更改图片时都会占用更多内存。我以为 pic.image = [picArr objectAtIndex:i+1] 只是告诉“pic”中的图像属性指向数组中的图像对象。我不知道。
  • 我们是否在您的问题中看到了您的整个界面 + 实现?如果没有 100% 的代码,我们可能看不到可能导致问题的所有内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-02
  • 2011-09-10
  • 2014-02-06
  • 2011-01-07
相关资源
最近更新 更多