2017-02-05 2 views
1

Я пытаюсь получить расчет гистограммы. Все работает отлично, за исключением того, что следующий метод показывает огромную утечку памяти при профилировании в Инструментах.vImageBuffer_InitWithCGImage Утечка памяти в Swift 3

Каждый раз, когда следующий метод вызывается, он использует 200-300 Мб оперативной памяти и никогда не выпускает:

 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) 
} 

Что может быть неправильно здесь .....

ответ

2

Документов для vImageBuffer_InitWithCGImage объяснить:

Вы несете ответственность за возврат памяти, на которую ссылаются данные buf->, в систему, используя free(), когда вы закончите с ней.

Так что я бы ожидать чего-то вдоль этих линий, чтобы очистить память:

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

Как примечание стороны, ваше использование UnsafeMutablePointer здесь не безопасно. Нет никакого обещания, например, что alpha будет существовать к моменту использования ссылки. Свифт может уничтожить alpha сразу же после создания alphaPtr (потому что он никогда не упоминается снова). Редко вы хотите использовать 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)) 
       } 
      } 
     } 
    } 
} 
+0

БОЛЬШОЙ ответ! Работает! – Gizmodo

+1

Я считаю, что бесплатный (inBuffer.data) также сработал бы? – Gizmodo

+1

hahaha yeah ... Я забыл, что 'free' будет импортироваться через' Darwin' (тратил так много времени на сырой Swift). Наверное, даже лучше назвать то, что они говорят, чтобы позвонить ... –

Смежные вопросы