我在我的应用程序中启用了ARC,并注意到如果创建大量图像,我的应用程序将崩溃。作为调查的一部分,我创建了一个小项目,再现了here处的问题。示例项目代码的内容如下:
int width = 10;
int height = 10;
uint8_t data[100];
while (true)
{
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
CGContextRef context = CGBitmapContextCreate(data, width, height, 8, width, colorspace, kCGBitmapByteOrderDefault | kCGImageAlphaNone);
CGImageRef cgimage = CGBitmapContextCreateImage(context);
// Remove this line and memory is stable, keep it and you lose 15-20 MB per second. Why?
UIImage* uiimage = [UIImage imageWithCGImage:cgimage];
CGImageRelease(cgimage);
CGContextRelease(context);
CGColorSpaceRelease(colorspace);
}
运行此代码时,Xcode的侧边栏将显示应用程序的总内存以每秒15-20 MB的速度增加。如果您注释掉创建UIImage
的行,则泄漏将消失。
关于Stack Overflow的问题很多,关于在通过CGImage
创建UIImage之后是否应该释放imageWithCGImage
的问题,似乎并没有达成共识。但是,如果我不打CGImageRelease(cgimage)
,则每秒的内存使用量会增加100 MB以上,因此,我确定手动释放映像是正确的做法。
由于我已启用ARC,因此我在释放所有内容后尝试将uiimage
设置为nil
,但没有成功。不存储对imageWithCGImage:
的调用的返回值也不能防止泄漏。
在使用Core Graphics方面我是否缺少一些基本知识?
答案 0 :(得分:1)
在使用Core Graphics方面我是否缺少一些基本知识?
您似乎很可能缺少有关内存管理的一些基本知识。
许多Foundation / Cocoa框架命令,尤其是那些创建现成对象的命令,都会使它们成为自动发布的对象。这意味着您不必释放对象,因为使用完该对象后,它会自动释放。但是那怎么可能呢?这些对象进入自动释放池,一旦它们的保留计数下降到零,它们就会在有机会的时候被耗尽。但是您在不断循环,因此没有这样的机会。因此,您需要将麻烦的行包装在@autoreleasepool{}
块中,以构造和消耗自己的池。
还请注意,可能存在您不知道的中间自动释放对象。自动释放池也可以为您提供帮助。
有关自动释放对象的更多信息,请参见this section of my book。