'UnsafeMutableRawPointer' 的初始化导致悬空指针

Mar*_*usM 11 swift

从 Xcode 11.4 开始,我收到警告消息“'UnsafeMutableRawPointer' 的初始化导致悬空指针”

对于以下代码,我将 SIMD4 从 MTLTexture 读取到数组中:

let texArray = Array<SIMD4<Float>>(repeating: SIMD4<Float>(repeating: 0), count: 1)

texture.getBytes(UnsafeMutableRawPointer(mutating: texArray), bytesPerRow: (MemoryLayout<SIMD4<Float>>.size * texture.width), from: region, mipmapLevel: 0)
Run Code Online (Sandbox Code Playgroud)

有人可以弄清楚如何创建数组指针以消除警告吗?

谢谢

das*_*obu 20

TLDR

使文本数组可变(使用var而不是let)并使用withUnsafeMutableBytes

var texArray = Array<SIMD4<Float>>(repeating: SIMD4<Float>(repeating: 0), count: 1)
texArray.withUnsafeMutableBytes { texArrayPtr in
    texture.getBytes(texArrayPtr.baseAddress!, bytesPerRow: (MemoryLayout<SIMD4<Float>>.size * texture.width), from: region, mipmapLevel: 0)
}
Run Code Online (Sandbox Code Playgroud)

解释

引入警告是因为编译器无法确保支持指针的数据不会被释放。考虑您有一个函数(例如在 C 中实现)操作一些指向的数据。

func f(_ a: UnsafeMutablePointer<Int>){
  a[0] = 42
}
Run Code Online (Sandbox Code Playgroud)

然后必须确保直到调用结束内存才被释放。所以当以下面的方式调用这个函数是不安全的

var a: = [1]
p: UnsafeMutablePointer<Int>(&a)
// at this point the compiler may optimise and deallocate 'a' since it is not used anymore
f(p)
Run Code Online (Sandbox Code Playgroud)

目前,据我所知,这不是问题,因为局部变量不会在作用域结束之前被释放。可以通过以下方式引入嵌套范围来说明可能的问题

var a: = [1]
p: UnsafeMutablePointer<Int>(&a)
// at this point the compiler may optimise and deallocate 'a' since it is not used anymore
f(p)
Run Code Online (Sandbox Code Playgroud)

由于b分配的内存与a之前使用的内存相同,因此b调用 来修改的内存f(p!)b[0]42 也是如此,尽管它被初始化0并没有明确修改。

有了这个插图,应该清楚为什么会有方法withUnsafeMutableByteswithUnsafeMutableBufferPointerSwift 数组和全局函数withUnsafeMutablePointer以及不可变变体。(我个人觉得必须在数组上使用方法和结构上的全局函数是令人困惑的。)这些函数确保内存不会在闭包的范围内被释放(或重用)(我还创建了一些示例的要点)。