Ios 为什么CIContext.createCGImage会导致内存泄漏?
我只在iOS 9上观察到这种行为;iOS 8工作正常 我怀疑这可能是SDK上的一个bug,我已经打开了苹果(22644754)的雷达,但我发现它太奇怪了,以至于我觉得我可能错过了一个电话或一个避免泄漏的步骤 我观察到,每次调用CIContext.createCGImage时,内存使用量都会增加。棘手的是,内存增加发生在应用程序之外 如果您查看Xcode中的“内存报告”,可以在“其他进程”部分看到内存的增加 基本上,造成问题的原因如下(我已将代码简化为重现泄漏所需的部分): 首先,我创建了一个由EAGLContext支持的CIContext:Ios 为什么CIContext.createCGImage会导致内存泄漏?,ios,memory-leaks,opengl-es,ios9,core-image,Ios,Memory Leaks,Opengl Es,Ios9,Core Image,我只在iOS 9上观察到这种行为;iOS 8工作正常 我怀疑这可能是SDK上的一个bug,我已经打开了苹果(22644754)的雷达,但我发现它太奇怪了,以至于我觉得我可能错过了一个电话或一个避免泄漏的步骤 我观察到,每次调用CIContext.createCGImage时,内存使用量都会增加。棘手的是,内存增加发生在应用程序之外 如果您查看Xcode中的“内存报告”,可以在“其他进程”部分看到内存的增加 基本上,造成问题的原因如下(我已将代码简化为重现泄漏所需的部分): 首先,我创建了一个由E
let glContext = EAGLContext(API: .OpenGLES2)!
let ciContext = CIContext(EAGLContext: glContext, options: [kCIContextOutputColorSpace : NSNull()])
然后,我使用以下方法渲染图像:
let input = CIImage(image: UIImage(named: "DummyImage")!)!
ciContext.createCGImage(input, fromRect: input.extent)
DummyImage只是一个示例图像文件。泄漏与此图像的大小直接相关,因此最好使用较大的泄漏,以使问题更加明显
如您所见,我没有使用任何CIFILTER(使用它们会导致相同的结果),也没有捕获结果图像(即使捕获了它,也无法使用CGImageRelease,因为对象是自动管理的)
如果渲染代码执行的次数足够多,内存将增长太多,以至于运行的应用程序将被杀死
一个有趣的观察结果是,销毁CIContext没有什么区别,但销毁EagleContext确实会返回所获取的内存。这让我认为泄漏发生在OpenGL方面
我的代码中是否缺少任何可能导致泄漏的内容?我能打个电话来释放EagleContext占用的内存吗?(始终重新创建它不是一个选项,因为这是一个成本高昂的操作)
我创建了一个简单的项目来重现这个问题。您可以在以下网址找到: 复制的步骤是:
我解决这个问题的方法是将上下文呈现到缓冲区中,然后将其作为JPG写入文件。我必须进一步了解如何在旧一代iOS设备上优化此流程,但与createCGImage相比,它似乎工作得很好。此代码对于将CIImage转换为JPEG或位图数据也很有用。完整的示例代码可以在这里看到:
这已被确认为iOS 9上的一个bug。该问题已在iOS 9.1 beta 3上解决
原始问题中的代码是正确的。在iOS 9之前的版本或从iOS 9.1 Beta 3开始的版本上,不需要进行任何修改来防止泄漏。为什么
bytesperpoixel=8
?kciformatrba8不是每像素4字节的格式吗?
static CIContext *ctx = nil;
if (!ctx)
{
ctx = [CIContext contextWithOptions:@{kCIContextWorkingColorSpace:[NSNull null]}];
}
CGSize bounds = enhancedImage.extent.size;
int bytesPerPixel = 8;
uint rowBytes = bytesPerPixel * bounds.width;
uint totalBytes = rowBytes * bounds.height;
uint8_t *byteBuffer = malloc(totalBytes);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
[ctx render:enhancedImage toBitmap:byteBuffer rowBytes:rowBytes bounds:enhancedImage.extent format:kCIFormatRGBA8 colorSpace:colorSpace];
CGContextRef bitmapContext = CGBitmapContextCreate(byteBuffer,bounds.width,bounds.height,bytesPerPixel,rowBytes,colorSpace,kCGImageAlphaNoneSkipLast);
CGImageRef imgRef = CGBitmapContextCreateImage(bitmapContext);
CGColorSpaceRelease(colorSpace);
CGContextRelease(bitmapContext);
free(byteBuffer);
if (imgRef == NULL) { goto release; }
CFURLRef url = (__bridge CFURLRef)[NSURL fileURLWithPath:filePath];
CGImageDestinationRef destination = CGImageDestinationCreateWithURL(url, kUTTypeJPEG, 1, NULL);
CGImageDestinationAddImage(destination, imgRef, nil);
CGImageDestinationFinalize(destination);
CFRelease(destination);
success = YES;
goto release;
release :
{
CFRelease(imgRef);
if (success)
{
//completionHandler(filePath);
}
dispatch_resume(_captureQueue);
}