CGImageRef 即使在释放后也会使用大量内存
Posted
技术标签:
【中文标题】CGImageRef 即使在释放后也会使用大量内存【英文标题】:CGImageRef uses lot of memory even after release 【发布时间】:2015-04-08 18:29:59 【问题描述】:我正在使用 CGImageRef 并注意到它使用了大量没有被释放的内存。 所以我尝试了以下代码
- (void)photofromAsset:(ALAsset *)asset completion:(void(^)(NSError *error))completionHandler
ALAssetRepresentation *representation = asset.defaultRepresentation;
UIImageOrientation orientation = (UIImageOrientation)representation.orientation;
CGImageRef fullResolutionImage = representation.fullResolutionImage;
//UIImage *fullImage = [UIImage imageWithCGImage:fullResolutionImage scale:0.0 orientation:orientation];
//[self startUpload:fullImage completion:completionHandler];
放置一些断点并将前三行代码放入@autorelease 池中。 然后尝试删除 @autorelease 并调用
CGImageRelease(fullResolutionImage);
当我到达 UIImageOrientation 时,我的应用使用的空间不到 30MB 但只要我调用 CGImageRef,它就会超过 80MB。 两种内存释放方法都只能让我达到 50MB,所以某处还有 20MB。 仅当整个方法完成时,才会释放额外的 20MB。
额外的 20MB 来自哪里? 在调用 startUpload: 之前如何释放它们?
谢谢
【问题讨论】:
"那些额外的 20MB 只有在整个方法完成后才会被释放" 但是如果它们随后被释放,你在乎什么? 我同意马特的观点。话虽如此,CoreGraphics 调用很难捕捉内存问题,但静态分析器(Xcode“产品”菜单上的“分析”)非常擅长捕捉任何漏掉的东西。确保您有一份来自分析仪的干净健康单。 @matt 问题在于,在该方法结束之前,我调用了相当长的 startUpload: 方法。同时我调用 photofromAsset: 很多次(甚至数百次),所以在释放 20MB 之前,另外 10 张图像将占用 10x20 MB,这会导致我的应用程序崩溃。 "我多次调用 photofromAsset:" 那么如果你将 那个 调用包装在一个自动释放池中并耗尽它呢? 【参考方案1】:你不需要手动释放CGImageRef,作为一个旧的CF opaque类型它遵循ownership的规则,你需要关心内存管理只有在函数/方法名称中有Create或Copy。
关于你的问题很难理解-startupload
做了什么以及你在哪里打电话给-photoFromAsset
。我的建议是,如果您在循环内调用 -photoFromAsset
,请将循环内的内容包装在 @autorelasePool 中。
其次可能是您的 startUpload (我想这是将某些内容上传到服务器),它通过解压缩并发送到服务器来继续保持对图像本身的强引用。
为了避免这种情况,也为了避免打开大量连接,我的建议是为网络操作创建一种队列,并“一次”仅发送 2 张图像。
【讨论】:
“我的建议是,如果您在循环内调用 -photoFromAsset,请将循环内的内容包装在 @autorelasePool 中”是的,这也是 my 的建议。 那为什么调用的时候有内存提升呢?问题是我正在做的上传需要能够继续在后台工作。这就是为什么我要尽快开始所有上传,以便操作系统知道它们并且用户可以在不停止文件上传的情况下退出应用程序。-startUpload:
为该照片设置请求,开始上传并仅在照片上传后返回。 -photoFromAsset:
已经在 @autorelasepool 中
@matt 看到我们达成一致对我来说是莫大的荣幸,我是你的忠实粉丝,我有你所有的书,对不起 OT,但我很高兴收到你的评论。
@halfblood17 你在使用任何网络库吗?因为在我看来,如果不对请求进行排队,您通常会使用大量资源,并且还可能导致网络问题。如果您关心用户关闭应用程序,您应该使用操作系统提供的所有特定方法,例如 beginBackgroundTaskWithName 或更好的 backgroundSessionConfigurationWithIdentifier: 用于 NSURLSession。当我需要发送图像时,我通常会收集它们并将它们保存在一个临时目录中,我不会一次将它们作为丢弃数据发送一次。
@halfblood17 您的问题似乎都源于您上传的图像(UIImage)保存在内存中(变量fullImage
,已注释掉在您引用的代码中)。这似乎是一件非常愚蠢的事情:图像很大。为什么不将 UIImage write 到磁盘,这样您就可以上传 file(从磁盘),而无需将 anything 保存在内存中?【参考方案2】:
您的问题似乎都源于您上传的图像(UIImage)在内存中(变量fullImage
,在您引用的代码中注释掉)。这似乎是一件非常愚蠢的事情:图片很大,上传需要时间,所以您强制程序将整个图片保存在内存中,直到上传为止。 p>
相反,你为什么不立即写入 UIImage 作为文件到磁盘,这样你就可以从内存 中释放图像并上传文件(从磁盘),没有在内存中保存任何东西?
【讨论】:
以上是关于CGImageRef 即使在释放后也会使用大量内存的主要内容,如果未能解决你的问题,请参考以下文章
Sqoop 导入失败:请使用 --split-by 指定一个或使用 '-m 1' 执行顺序导入 即使在设置 mapper = 1 后也会出错