Swift 3 CGContext 内存泄漏
Posted
技术标签:
【中文标题】Swift 3 CGContext 内存泄漏【英文标题】:Swift 3 CGContext Memory Leak 【发布时间】:2017-04-11 07:48:21 【问题描述】:我正在使用 CGBitMapContext() 将颜色空间转换为 ARGB 并获取像素数据值,我为位图上下文分配空间并在完成后释放它,但我仍然在仪器中看到内存泄漏我想我可能做错了什么,所以任何帮助将不胜感激。
这里是 ARGBBitmapContext 函数
func createARGBBitmapContext(width: Int, height: Int) -> CGContext
var bitmapByteCount = 0
var bitmapBytesPerRow = 0
//Get image width, height
let pixelsWide = width
let pixelsHigh = height
bitmapBytesPerRow = Int(pixelsWide) * 4
bitmapByteCount = bitmapBytesPerRow * Int(pixelsHigh)
let colorSpace = CGColorSpaceCreateDeviceRGB()
// Here is the malloc call that Instruments complains of
let bitmapData = malloc(bitmapByteCount)
let context = CGContext(data: bitmapData, width: pixelsWide, height: pixelsHigh, bitsPerComponent: 8, bytesPerRow: bitmapBytesPerRow, space: colorSpace, bitmapInfo: CGImageAlphaInfo.premultipliedFirst.rawValue)
// Do I need to free something here first?
return context!
这里是我使用上下文检索所有像素值作为 UInt8 列表的地方(以及内存泄漏的地方)
extension UIImage
func ARGBPixelValues() -> [UInt8]
let width = Int(self.size.width)
let height = Int(self.size.height)
var pixels = [UInt8](repeatElement(0, count: width * height * 3))
let rect = CGRect(x: 0, y: 0, width: width, height: height)
let context = createARGBBitmapContext(inImage: self.cgImage!)
context.clear(rect)
context.draw(self.cgImage!, in: rect)
var location = 0
if let data = context.data
while location < (width * height)
let arrOffset = 3 * location
let offset = 4 * (location)
let R = data.load(fromByteOffset: offset + 1, as: UInt8.self)
let G = data.load(fromByteOffset: offset + 2, as: UInt8.self)
let B = data.load(fromByteOffset: offset + 3, as: UInt8.self)
pixels[arrOffset] = R
pixels[arrOffset+1] = G
pixels[arrOffset+2] = B
location += 1
free(context.data) // Free the data consumed, perhaps this isn't right?
return pixels
Instruments 报告了 1.48MiB 的 malloc 错误,这适合我的图像大小 (540 x 720) 我释放了数据,但显然这不正确。
我应该提一下,我知道你可以将 nil 传递给 CGContext init(它会管理内存),但我更好奇为什么使用 malloc 会产生问题,我应该知道更多的事情(我更熟悉 Obj -C)。
【问题讨论】:
我没有看到任何代码来释放上下文本身。完成上下文后,您需要致电CGContextRelease
。
CGContextRelease 在 Swift 3 中不可用,据我收集它释放自己(或至少应该)我不相信我已经创建了任何循环引用,所以它不会。
你找到答案了吗?
【参考方案1】:
因为 CoreGraphics 不是由 ARC 处理的(就像所有其他 C 库一样),所以即使在 Swift 中,您也需要使用自动释放来包装您的代码。特别是如果您不在主线程上(如果涉及 CoreGraphics,您不应该在主线程上...... .userInitiated 或更低是合适的)。
func myFunc()
for _ in 0 ..< makeMoneyFast
autoreleasepool
// Create CGImageRef etc...
// Do Stuff... whir... whiz... PROFIT!
对于那些关心的人,你的 Objective-C 也应该像这样包装:
BOOL result = NO;
NSMutableData* data = [[NSMutableData alloc] init];
@autoreleasepool
CGImageRef image = [self CGImageWithResolution:dpi
hasAlpha:hasAlpha
relativeScale:scale];
NSAssert(image != nil, @"could not create image for TIFF export");
if (image == nil)
return nil;
CGImageDestinationRef destRef = CGImageDestinationCreateWithData((CFMutableDataRef)data, kUTTypeTIFF, 1, NULL);
CGImageDestinationAddImage(destRef, image, (CFDictionaryRef)options);
result = CGImageDestinationFinalize(destRef);
CFRelease(destRef);
if (result)
return [data copy];
else
return nil;
详情请见this answer。
【讨论】:
以上是关于Swift 3 CGContext 内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章