Swift 3 CGContext Memory Leak
我正在使用CGBitMapContext()将色彩空间转换为ARGB并获取像素数据值,我为位图上下文分配了空间,并在完成后将其释放,但仍然在仪器中看到内存泄漏我以为我可能做错了什么,因此我们将不胜感激。
这是ARGBBitmapContext函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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! } |
这里是我使用上下文检索所有像素值作为UInt8s列表的地方(以及内存泄漏的地方)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 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 } } |
仪器报告一个malloc错误1.48MiB,适合我的图像大小(540 x 720),我释放了数据,但显然那是不正确的。
我应该提一下,我知道您可以将nil传递给CGContext init(它将管理内存),但是我很好奇为什么使用malloc会产生一个问题,我应该了解更多信息(我更熟悉使用Obj-C)。
由于CoreGraphics不是由ARC处理的(像所有其他C库一样),因此即使在Swift中,也需要使用自动发布来包装代码。特别是如果您不在主线程上(如果涉及CoreGraphics,则不应该在主线程上... .userInitiated或更低版本是适当的)。
1 2 3 4 5 6 7 8 | func myFunc() { for _ in 0 ..< makeMoneyFast { autoreleasepool { // Create CGImageRef etc... // Do Stuff... whir... whiz... PROFIT! } } } |
对于那些关心的人,您的Objective-C也应该像这样包装:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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; } |
有关详细信息,请参见此答案。