加载UIImage时iOS应用程序崩溃(虚拟内存未清理)

时间:2013-05-29 04:52:16

标签: objective-c crash uiimage virtual-memory

我的应用程序中有一个奇怪的崩溃,没有任何痕迹。这可能是一个与记忆有关的问题,但信息很少,而且我不知道如何进行或修复它。如果它不是仪器本来就没有任何线索。

我有一个图像数组(在本例中是一个大小为2的数组),我在其中加载图像,创建图像上下文&绘制并将其保存到数组中。每次调用该方法时,图像数组对象都会被新内容替换。在仪器中,我看到在此方法调用期间使用非常大的虚拟内存。显然在每次通话记忆后都没有清除&因此崩溃。该项目是ARC。我将在下面列出代码。这就是我们重新创建此问题所需的全部内容。 (我使用的图像大小约为7MB,因此更容易重新创建崩溃)。我也在使用iPad2设备。

+ (UIImage *)imageCopy:(UIImage *)src
{
    UIGraphicsBeginImageContext(src.size);
    [src drawAtPoint:CGPointZero];
    UIImage *r = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return r;
} 

- (IBAction)buttonTouch:(id)sender
{
    for (int i=0; i<2; i++)
    {
        if (i==0)
        {
            self.mImage = [UIImage imageNamed:@"LARGE_elevation.jpg"];
        }
        else
        {
            self.mImage = [UIImage imageNamed:@"LARGE_elevation2.jpg"];
        }
        // imageArray is a NSMutableArray with capacity of 2
        [imageArray setObject:[ViewController imageCopy:self.mImage] atIndexedSubscript:i];
    }
    ((UIImageView *)[self.view viewWithTag:100]).image = self.mImage;
}

这是一个来自仪器的屏幕,在发出内存警告后第二次崩溃。

Instruments Screenshot

我没有看到我在这里使用的“imageCopy”方法有任何大问题。

对此的任何帮助都非常感谢。 谢谢&amp;欢呼声,

2 个答案:

答案 0 :(得分:1)

我发现这是 循环参考 问题。因此,当新内容替换数组中的旧内容时,过去的对象仍然存在。这是一个非常有趣的发现,因为在内存泄漏分析器中,它显示出很少的KB数据泄漏,你不会怀疑,因为非释放的虚拟内存是几百兆字节(MB)。

作为一个非常抽象的例子。

ClassA

@property (strong) ClassB *obj

----------

ClassB

@property (strong) ClassA *obj

- (id)initWithA:(ClassA *)objA;
----------

因此,当您删除A时,任何对象都不会被正确释放。在我的情况下,泄漏分析仪跟踪的泄漏对于两个对象都是几KB,即使CoreGraphics计算挂在虚拟内存中的大约200MB数据上。

修复是将ClassB中的A引用标记为弱。

ClassB

@property (weak) ClassA *obj

- (id)initWithA:(ClassA *)objA;

判决

  • 永远不要估计内存泄漏,无论大小有多大。 arc或mrc

答案 1 :(得分:0)

问题可能是方法imageNamed:缓存了加载的图像,并且显然无法以编程方式在内存警告后清除缓存。
您可以使用其他方法(例如imageNamed:)来缓存图像,而不是initWithData:。您将找到详细的讨论here