【问题标题】:Initialization of 'UnsafeMutableRawPointer' results in a dangling pointer'UnsafeMutableRawPointer' 的初始化导致悬空指针
【发布时间】:2023-11-10 02:03:01
【问题描述】:

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

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

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)

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

谢谢

【问题讨论】:

    标签: swift


    【解决方案1】:

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

    说明

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

    func f(_ a: UnsafeMutablePointer<Int>){
      a[0] = 42
    }
    

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

    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)
    

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

    var p: UnsafeMutablePointer<Int>?
    do {
      var a = [1]
      p = UnsafeMutablePointer<Int>(&a)
    } // "a" will be deallocated here
    // now "p" is a dangling pointer the compiler warned you of
    var b = [0] // compiler will use same memory as for "a", so manipulating memory of "p" won't segfault
    f(p!) // manipulate memory
    print(b[0]) // prints 42 although "b" was initialised to 0
    

    由于b 分配的内存与a 之前使用的内存相同,因此b 的内存通过调用f(p!) 被修改。所以b[0] 是 42,尽管它被初始化为 0 并且没有显式修改。

    有了这张图,应该很清楚为什么 Swift 数组上有方法 withUnsafeMutableByteswithUnsafeMutableBufferPointer 以及全局函数 withUnsafeMutablePointer 以及不可变的变体。 (我个人觉得必须在数组上使用方法和在结构上使用全局函数,这让我感到困惑。) 这些函数确保不会在闭包范围内释放(或重用)内存(我还通过一些示例创建了gist)。

    【讨论】:

    • 很好的答案,谢谢。解说也很有帮助!