gpt4 book ai didi

ios - 为什么 CIContext.createCGImage 会导致内存泄漏?

转载 作者:可可西里 更新时间:2023-11-01 03:34:14 25 4
gpt4 key购买 nike

我只在 iOS 9 上观察到这种行为; iOS 8 正常运行。

我怀疑这可能是 SDK 上的一个错误,我已经向 Apple (22644754) 打开了一个雷达,但我发现它很奇怪,我觉得我可能错过了一个电话或一个步骤来避免泄漏。

我观察到每次调用 CIContext.createCGImage 时,内存使用量都会增加。棘手的部分是内存增加发生在应用程序之外。

如果您查看 Xcode 的“内存报告”,内存增加会显示在“其他进程”部分。

基本上,导致问题的原因如下(我已将代码严格简化为重现泄漏所必需的部分):

首先,我创建一个由 EAGLContext 支持的 CIContext:

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 并没有什么不同,但销毁 EAGLContext 确实会返回占用的内存。这让我认为泄漏发生在 OpenGL 端。

我的代码中是否遗漏了任何可能导致泄漏的内容?我可以打电话释放 EAGLContext 占用的内存吗? (一直重新创建它不是一种选择,因为它是一项代价高昂的操作)。


我创建了一个简单的项目来重现该问题。您可以在以下位置找到它:

https://www.dropbox.com/s/zm19u8rmujv6jet/EAGLContextLeakDemo.zip?dl=0

重现的步骤是:

  1. 在设备上打开并运行附加项目。
  2. 观察 Xcode 上的“内存报告”屏幕。增长将在“使用比较”饼图的“其他进程”部分看到。
  3. 该应用程序显示三个按钮。他们每个人都会执行 createCGImage 命令一定次数(显示在按钮标签上)。
  4. 点击任何按钮都会导致“其他进程”的内存使用量增加。在执行几次 createCGImage 调用后,这可能会更加明显。
  5. 点击 100 Renders 按钮将更清楚地显示效果。
  6. 当内存增长过快时,App会崩溃。

最佳答案

我解决它的方法是将上下文呈现到缓冲区中,然后将其以 JPG 格式写入文件。我将不得不进一步了解如何在旧版 iOS 设备上优化此流程,但与 createCGImage 相比,它似乎运行良好。此代码对于将 CIImage 转换为 JPEG 或位图 NSData 也很有用。完整的示例代码可以在这里看到:

https://github.com/mmackh/IPDFCameraViewController

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);
}

关于ios - 为什么 CIContext.createCGImage 会导致内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32520082/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com