CGImage创建了大量的脏内存,导致应用程序崩溃。

4
我尝试通过填充自己的数据来创建UIImage。到目前为止,一切都很顺利。但是,如果我尝试多次调用此函数,它似乎会填充内存直到应用程序崩溃。使用VM Tracker,我发现脏内存增长到328MB,其中当应用程序崩溃时,290MB是CG图像内存。
在启用ARC的情况下,我多次在循环中调用我的函数。图像相当大,但这不应该是问题,因为在前29次迭代中一切正常。据我所知,脏内存应该被应用程序再次重复使用。那正确吗?那么为什么它会填满我的内存,我该如何避免这个问题?
for(int i = 0; i < 1000; ++i) {
    UIImage *img = [self createDummyImage:CGSizeMake(2000, 1600)];
}

创建虚拟UIImage的函数:

- (UIImage*)createDummyImage:(CGSize)size
{
    unsigned char *rawData = (unsigned char*)malloc(size.width*size.height*4);

    // fill in rawData (logic to create checkerboard)

    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
    CGContextRef contextRef = CGBitmapContextCreate(rawData, size.width, size.height, 8, 4*size.width, colorSpaceRef, bitmapInfo);
    CGImageRef imageRef = CGBitmapContextCreateImage(contextRef);

    CGColorSpaceRelease(colorSpaceRef);
    CGContextRelease(contextRef);
    free(rawData);

    UIImage *image = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);

    return image;
}

hooleyhoop的工作解决方案

将函数调用放入自动释放池中。

for (int i = 0; i < 1000; ++i) {
    @autoreleasepool {
        UIImage *img = [self createDummyImage:CGSizeMake(2000, 1600)];
    }
}

为什么需要VM Tracker?Allocations工具告诉您有关实时内存的什么信息? - hooleyhoop
我收到了低内存报告,并根据“理解和分析iOS应用程序崩溃报告”(链接:http://developer.apple.com/library/ios/#technotes/tn2151/_index.html)发现需要使用VM Tracker来跟踪图形内存。实时内存似乎没问题。 - David Burri
你认为什么才算“OK”呢?我会非常惊讶…… - hooleyhoop
哦,我刚刚发现我只启用了跟踪活动分配。如果没有启用此功能,内存似乎不正常。总共有超过300MB的所有分配中的字节。 - David Burri
1个回答

5
我认为如果你在“分配”工具中查看“实时”内存,你会发现你只是正常内存不足 - 与脏VM无关。
这最可能是因为你有太多等待自动释放的内存。自动释放的对象直到当前自动释放池弹出才会被释放 - 你正在尝试向一个自动释放池添加数百兆字节的对象。
答案是管理你自己的自动释放池或不在一个事件循环中做太多的工作。
抱歉但我忍不住要做一些讽刺的评论... 在我的观点中,在ARC之前这应该更加明显。

谢谢,那就是问题所在!我现在使用一个定时器来调用该函数,它完美地工作了。 - David Burri
另一个选项是将工作块包装在 @autoreleasepool{ .. } 中。 - hooleyhoop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接