【问题标题】:UnsafeMutablePointer<Float> returned by vDSP_fft_zip being overwritten immediatelyvDSP_fft_zip 返回的 UnsafeMutablePointer<Float> 立即被覆盖
【发布时间】:2019-03-15 05:30:15
【问题描述】:

在 Swift 4 中,我正在创建一个 DSPSplitComplex 以在 vDSP_fft_zip() 中使用,但下次我创建另一个 DSPSplitComplex 时它会立即被覆盖。

(DSPSplitComplex结构有2个UnsafeMutablePointer&lt;Float&gt;)

//--Create the DSPSplitComplex    
var A = [Float](repeating:0, count:32); 
var B = [Float](repeating:0, count:32)
var splitComplex1 = DSPSplitComplex(realp: &A, imagp: &B)

//--Perform fft
log2Size = vDSP_Length(log2f(Float(32)))
setupFFT = vDSP_create_fftsetup(log2Size, FFTRadix(FFT_RADIX2))!;
vDSP_fft_zip(setupFFT, & splitComplex1, 1, log2Size, FFTDirection(FFT_FORWARD));

//--Create another DSPSplitComplex    
var C = [Float](repeating:0, count:32); 
var D = [Float](repeating:0, count:32)
var splitComplex2 = DSPSplitComplex(realp: &C, imagp: &D)

我现在可以在调试器中看到 splitComplex2.realp 的 UnsafeMutablePointer 与 splitComplex1.realp 的地址相同,因此我对 splitComplex2 所做的任何事情都会覆盖 splitComplex1

我猜线索可能在标题“不安全”中,但如果它实际上不可用,那么存储返回的 DSPSplitComplex 内容的正确策略是什么?

我想从它们创建新的 [Float] 数组是制作永久副本的一种方式

let arrary = Array(UnsafeBufferPointer(start: splitComplex1.realp, count: 32))

...但似乎,尽管阅读了 Swift 文档,但我仍然误解了 UnsafeMutablePointer 的意义,为什么 vDSP_fft_zip() 会返回从一开始就无法使用的东西?

【问题讨论】:

  • 从它的样子来看,DSPSplitComplex 不会获取您传递给它的缓冲区的自己的副本,因此它存储了两个悬空指针(悬空是因为 inout 到指针的参数转换只产生指针在通话期间有效)。根据您的需要,您可以使用ArraywithUnsafeMutableBufferPointer 方法来获得对底层内存的范围访问。但是如果你需要更多的灵活性,我会考虑创建一个类包装器类型来分配必要的内存并在deinit 中释放它(你可以使用ManagedBuffer 来提高内存效率)
  • 谢谢,我明白了,使用 withUnsafeMutableBufferPointer 解决了。

标签: swift vdsp unsafemutablepointer


【解决方案1】:

你创建DSPSplitComplex的方式是错误的。

当您使用&amp;Array&lt;Float&gt; 传递给UnsafeMutablePointer&lt;Float&gt; 时,传递给函数的地址仅在函数内部有效。

因此,在您的代码中,当 DSPSplitComplex 的初始化程序完成时,通过 DSPSplitComplex(realp: &amp;A, imagp: &amp;B) 的两个地址无效。

为避免这种行为,您可以尝试以下方法:

var A = [Float](repeating:0, count:32)
var B = [Float](repeating:0, count:32)
A.withUnsafeMutableBufferPointer {aumbp in
    B.withUnsafeMutableBufferPointer {bumbp in
        var splitComplex1 = DSPSplitComplex(realp: aumbp.baseAddress!, imagp: bumbp.baseAddress!)

        //--Perform fft
        let log2Size = vDSP_Length(log2f(Float(32)))
        let setupFFT = vDSP_create_fftsetup(log2Size, FFTRadix(FFT_RADIX2))!
        vDSP_fft_zip(setupFFT, &splitComplex1, 1, log2Size, FFTDirection(FFT_FORWARD))
    }
}

否则,您可以分配UnsafeMutableBufferPointer&lt;Float&gt;s 并使用它们而不是Array&lt;Float&gt;

【讨论】:

  • 完美运行,谢谢(我花了几分钟才了解关闭情况)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-17
  • 1970-01-01
  • 2011-07-19
  • 2021-02-27
  • 2010-10-14
相关资源
最近更新 更多