Xcode UIImage imageWithCGImage 泄漏内存

Xcode UIImage imageWithCGImage leaks memory

我在我的应用程序中启用了 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 上有很多关于在通过 imageWithCGImage 创建 UIImage 后是否应该发布 CGImage 的问题,看起来并没有真正的共识.但是,如果我不调用 CGImageRelease(cgimage),那么内存使用量会以每秒超过 100 MB 的速度增加,所以我确信手动释放图像是正确的做法。

因为我启用了 ARC,我尝试在释放所有内容后将 uiimage 设置为 nil,但没有用。不存储调用 imageWithCGImage: 的 return 值也不能防止泄漏。

关于如何使用 Core Graphics,我是否遗漏了一些基本知识?

Is there something fundamental I'm missing about how to use Core Graphics?

您似乎更有可能遗漏了有关内存管理的一些基本知识。

许多 Foundation / Cocoa 框架命令,尤其是那些创建 ready-made 对象的命令,使对象成为 autoreleased。这意味着您不必释放该对象,因为它会在您完成处理后自动释放。但这怎么可能呢?这些对象进入 autorelease pool,一旦它们的保留计数降为零,它们就会在以后有机会时被耗尽。但是你是不断循环的,所以没有这样的机会。因此,您需要将麻烦的行包装在 @autoreleasepool{} 块中,以便构建和排空您自己的池。

另请注意,可能存在您不知道的中间自动释放对象。自动释放池也可以帮助解决这些问题。

有关自动释放对象的详细信息,请参阅 this section of my book