【问题标题】:vImageBuffer_InitWithCGImage Memory Leak in Swift 3Swift 3 中的 vImageBuffer_InitWithCGImage 内存泄漏
【发布时间】:2017-06-22 16:08:28
【问题描述】:

我正在尝试进行直方图计算。一切正常,除了以下方法在 Instruments 中分析时显示出巨大的内存泄漏。

每次调用以下方法时,它使用 200-300 MB 的内存并且从不释放:

       func histogramCalculation(_ imageRef: CGImage) -> (red: [UInt], green: [UInt], blue: [UInt]) {

            var inBuffer = vImage_Buffer() 

            vImageBuffer_InitWithCGImage(
                &inBuffer,
                &format,
                nil,
                imageRef,
                UInt32(kvImageNoFlags))

            let alpha = [UInt](repeating: 0, count: 256)
            let red = [UInt](repeating: 0, count: 256)
            let green = [UInt](repeating: 0, count: 256)
            let blue = [UInt](repeating: 0, count: 256)

            let alphaPtr = UnsafeMutablePointer<vImagePixelCount>(mutating: alpha) as UnsafeMutablePointer<vImagePixelCount>?
            let redPtr = UnsafeMutablePointer<vImagePixelCount>(mutating: red) as UnsafeMutablePointer<vImagePixelCount>?
            let greenPtr = UnsafeMutablePointer<vImagePixelCount>(mutating: green) as UnsafeMutablePointer<vImagePixelCount>?
            let bluePtr = UnsafeMutablePointer<vImagePixelCount>(mutating: blue) as UnsafeMutablePointer<vImagePixelCount>?

            let rgba = [redPtr, greenPtr, bluePtr, alphaPtr]

            let histogram = UnsafeMutablePointer<UnsafeMutablePointer<vImagePixelCount>?>(mutating: rgba)
            let error : vImage_Error = vImageHistogramCalculation_ARGB8888(&inBuffer, histogram, UInt32(kvImageNoFlags))

            if (error == kvImageNoError) {
                return (red, green, blue)
            }
            return (red, green, blue)
}

这里有什么问题.....

【问题讨论】:

    标签: ios xcode memory-leaks swift3 histogram


    【解决方案1】:

    vImageBuffer_InitWithCGImage 的文档解释:

    您有责任在完成后使用 free() 将 buf->data 引用的内存返回给系统。

    所以我希望按照以下方式清理内存:

    inBuffer.data.deallocate(bytes: inBuffer.rowBytes * Int(inBuffer.height),
                             alignedTo: MemoryLayout<vImage_Buffer>.alignment)
    

    附带说明,您在此处使用UnsafeMutablePointer 并不安全。例如,没有保证 alpha 在您使用引用时会存在。允许 Swift 在您创建 alphaPtr 后立即销毁 alpha(因为它再也不会被引用)。您很少使用UnsafeMutablePointer.init。相反,您想使用withUnsafe... 方法来建立保证生命周期。例如(未经测试,但可以编译):

    var alpha = [vImagePixelCount](repeating: 0, count: 256)
    var red = [vImagePixelCount](repeating: 0, count: 256)
    var green = [vImagePixelCount](repeating: 0, count: 256)
    var blue = [vImagePixelCount](repeating: 0, count: 256)
    
    let error = alpha.withUnsafeMutableBufferPointer { alphaPtr -> vImage_Error in
        return red.withUnsafeMutableBufferPointer { redPtr in
            return green.withUnsafeMutableBufferPointer { greenPtr in
                return blue.withUnsafeMutableBufferPointer { bluePtr in
                    var rgba = [redPtr.baseAddress, greenPtr.baseAddress, bluePtr.baseAddress, alphaPtr.baseAddress]
                    return rgba.withUnsafeMutableBufferPointer { buffer in
                        return vImageHistogramCalculation_ARGB8888(&inBuffer, buffer.baseAddress!, UInt32(kvImageNoFlags))
                    }
                }
            }
        }
    }
    

    【讨论】:

    • 很好的答案!有效!
    • 我相信 free(inBuffer.data) 也会起作用?
    • 哈哈哈是的……我忘记了 free 将通过 Darwin 导入(在原始 Swift 中花费了很多时间)。可能更好地调用他们所说的调用......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-19
    • 2021-03-19
    • 1970-01-01
    • 1970-01-01
    • 2015-02-21
    • 2016-03-28
    相关资源
    最近更新 更多