简体   繁体   English

为什么用CGImageSource加载gif会导致内存泄漏?

[英]Why does loading a gif with CGImageSource cause a memory leak?

I have a gif file in my project. 我的项目中有一个gif文件。 I am trying to display that gif file in my UIImageView . 我试图在我的UIImageView显示该gif文件。 Here is my code: 这是我的代码:

NSData* gifOriginalImageData = [NSData dataWithContentsOfURL:url];// url of the gif file
CGImageSourceRef src = CGImageSourceCreateWithData((CFDataRef)gifOriginalImageData, NULL);

NSMutableArray *arr = [[NSMutableArray alloc] init];

NSInteger imagesCountInGifFile = CGImageSourceGetCount(src);
CGImageRef imagesOut[imagesCountInGifFile];
for (int i = 0; i < imagesCountInGifFile; ++i) {
    [arr addObject:[UIImage imageWithCGImage:CGImageSourceCreateImageAtIndex(src, i, NULL)]];
}

self.onboardingImageView.animationImages = arr;
self.onboardingImageView.animationDuration = 1.5;
self.onboardingImageView.animationRepeatCount = 2;
[self.onboardingImageView startAnimating];

I can display the gif file successfully with this code. 我可以使用此代码成功显示gif文件。 However it causes a memory leak up to 250mb with 60 images. 但是,这会导致60张图像的最大内存泄漏为250mb。 I have tried to reduce the memory with the given code however there is no success again. 我试图用给定的代码减少内存,但是再也没有成功。

self.onboardingImageView.animationImages = nil;
CFRelease(src);

Any help would be appreciated. 任何帮助,将不胜感激。 Edit: I have added an 编辑:我添加了 图片 which is a potentially leak. 这是潜在的泄漏。

If a function has the word Create in it, that's an indication that you're responsible for releasing the memory of the thing that it returns. 如果函数中包含“ Create ”一词,则表明您有责任释放它返回的内容。 In this case, the documentation of CGImageSourceCreateImageAtIndex explicitly says: 在这种情况下, CGImageSourceCreateImageAtIndex 的文档明确指出:

Returns a CGImage object. 返回一个CGImage对象。 You are responsible for releasing this object using CGImageRelease. 您有责任使用CGImageRelease释放此对象。

You are repeatedly calling CGImageSourceCreateImageAtIndex , but never actually releasing the CGImage that it returns, therefore resulting in a memory leak. 您反复调用CGImageSourceCreateImageAtIndex ,但从未实际释放它返回的CGImage ,因此导致内存泄漏。 The general rule of thumb is for every call to a function that has the word Create in it – you should have an equivalent release. 一般的经验法则是,每次调用函数中都带有“ Create ”一词的函数时,都应该有一个等效的版本。

I also don't see the point in having an array of your CGImages (as you create an array of UIImages ). 我也看不到拥有CGImages数组的CGImages (在创建UIImages数组时)。 This means that all you have to do is create your CGImage at each iteration of the loop, wrap it in a UIImage , add this image to your array and then finally release the CGImage . 这意味着您要做的就是在循环的每次迭代中创建CGImage ,将其包装在UIImage ,将此图像添加到数组中,然后最终释放CGImage For example: 例如:

CGImageSourceRef src = CGImageSourceCreateWithData((__bridge CFDataRef)gifOriginalImageData, NULL);

NSMutableArray *arr = [[NSMutableArray alloc] init];

NSInteger imagesCountInGifFile = CGImageSourceGetCount(src);
for (int i = 0; i < imagesCountInGifFile; ++i) {
    CGImageRef c = CGImageSourceCreateImageAtIndex(src, i, NULL); // create the CGImage
    [arr addObject:[UIImage imageWithCGImage:c]]; // wrap that CGImage in a UIImage, then add to array
    CGImageRelease(c); // release the CGImage <- This part is what you're missing!
}

CFRelease(src); // release the original image source

Note that you should also be bridging your gifOriginalImageData instead of casting (I assume you're using ARC). 请注意,您还应该桥接gifOriginalImageData而不是强制转换(我假设您正在使用ARC)。

With the changes, the above code runs fine without any memory leaks. 进行更改后,以上代码可以正常运行,而不会发生任何内存泄漏。

You'll want to work with an array of NSData vs. an array of UIImage. 您将要使用NSData数组和UIImage数组。 Image data is compressed by default and working with a UIImage decompresses the data. 图像数据默认情况下是压缩的,并且使用UIImage可以解压缩数据。

Also, UIImage has some caching under the hood that can be hard on memory. 同样,UIImage在后台有一些缓存,可能很难存储。

Michael Behan wrote a great blog post on the topic: http://mbehan.com/post/78399605333/uiimageview-animation-but-less-crashy 迈克尔·贝汉(Michael Behan)就该主题写了一篇很棒的博客文章: http : //mbehan.com/post/78399605333/uiimageview-animation-but-less-crashy

And he wrote a helpful library (MIT License) to prevent this from happening: https://github.com/mbehan/animation-view 他写了一个有用的库(MIT许可证)来防止这种情况的发生: https : //github.com/mbehan/animation-view

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM