警告:'UnsafeBufferPointer<T>' 的初始化导致悬空的缓冲区指针

Exe*_*eev 32 unsafe-pointers swift swift5.2 xcode11.4

更新到 Swift 5.2 / Xcode 11.4 后收到以下代码警告:

extension Data {

    init<T>(from value: T) {
        var value = value
        let pointer = UnsafeBufferPointer(start: &value, count: 1)
        self.init(buffer: pointer)
    }

    func to<T>(type: T.Type) -> T {
        return self.withUnsafeBytes { $0.load(as: T.self) }
    }
}
Run Code Online (Sandbox Code Playgroud)

在线let pointer = UnsafeBufferPointer(start: &value, count: 1)我得到了

'UnsafeBufferPointer' 的初始化导致悬空的缓冲区指针

我可以使用@silenceWarning,但这是一个肮脏的解决方案。也许我需要将指针存储在某处并在将来清理它?

Che*_* OT 15

我也遇到了这些烦人的警告。

var str = "aaaaabbbbbccccc"
var num1 = 1
var num2 = 22

var data = Data()
// Initialization of 'UnsafeBufferPointer<String>' results in a dangling buffer pointer
data.append(UnsafeBufferPointer(start: &str, count: 1)) 
// Initialization of 'UnsafeBufferPointer<Int>' results in a dangling buffer pointer
data.append(UnsafeBufferPointer(start: &num1, count: 1))
// Initialization of 'UnsafeBufferPointer<Int>' results in a dangling buffer pointer 
data.append(UnsafeBufferPointer(start: &num2, count: 1)) 
Run Code Online (Sandbox Code Playgroud)

考虑到@greg 的回答,我将 in 的闭包Data.append放入withUnsafePointer,并且不再显示警告。

withUnsafePointer(to: &str) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } // ok
withUnsafePointer(to: &num1) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } // ok
withUnsafePointer(to: &num2) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } // ok
Run Code Online (Sandbox Code Playgroud)

这是扩展名

extension Data {
    init<T>(value: T) {
        self = withUnsafePointer(to: value) { (ptr: UnsafePointer<T>) -> Data in
            return Data(buffer: UnsafeBufferPointer(start: ptr, count: 1))
        }
    }

    mutating func append<T>(value: T) {
        withUnsafePointer(to: value) { (ptr: UnsafePointer<T>) in
            append(UnsafeBufferPointer(start: ptr, count: 1))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 11

我的代码看起来几乎与您在做什么并且收到相同的警告。我的与讨论有关的方式略有不同

init<T>(from value: T) {
    var value = value
    self.init(buffer: UnsafeBufferPointer(start: &value, count: 1))
}
Run Code Online (Sandbox Code Playgroud)

这仍然会生成警告,即 UnsafeBufferPointer 正在生成一个悬空指针,但提示说“生成一个仅在调用 'init(start:count:)' 期间有效的指针”

但是 UnsafeBufferPointer 的返回值没有分配给任何东西,所以如果我尝试的话,我不能在 init 的范围之外使用它。所以这里的编译器警告我不要做我无论如何都做不到的事情。

我猜 Data.init(buffer: ) 可能正在存储 ptr,但我认为如果它接受 UnsafeBufferPointer,它就承担了正确使用它的责任

无论如何,这仍然不能真正解决您的问题。我绕过了这个警告

init<T>(from value: T) {
    var value = value
    var myData = Data()
    withUnsafePointer(to:&value, { (ptr: UnsafePointer<T>) -> Void in
        myData = Data( buffer: UnsafeBufferPointer(start: ptr, count: 1))
    })
    self.init(myData)
}
Run Code Online (Sandbox Code Playgroud)

这不会产生警告并且似乎可以工作(无论如何在我的应用程序中)。能否与这里的专家一起通过是另一回事。

有点让我怀念 HLock 和 HUnlock 的日子


Rob*_*ier 6

这从来都不是安全的,很高兴 Swift 团队已经清理了它:

let pointer = UnsafeBufferPointer(start: &value, count: 1)
Run Code Online (Sandbox Code Playgroud)

在这行代码的末尾,pointer立即无效。没有承诺value甚至存在于下一行代码。我不确定你想在这里实现什么,但这从来都不是一种安全的方法。您可能正在寻找的是其中一种.withUnsafeBytes方法,这取决于您在做什么。

  • 虽然您的答案可能是正确的,但如果您能举例说明这可能会失败,那就更好了。有一些使用 Unsafe*Pointer 进行强制转换和转换的示例 (/sf/answers/1921935431/) 现在会生成此警告。 (6认同)