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。
我在我的应用程序中启用了 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。