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


10

在更新到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) }
    }
}

在网上让指针= UnsafeBufferPointer(开始:&值,计数:1)我得到了

初始化“ UnsafeBufferPointer”会导致缓冲区指针悬空

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


每个人都急于更新而又不花心地阅读发行说明,这是很奇怪的,这很奇怪。
马特·

Answers:


3

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

let pointer = UnsafeBufferPointer(start: &value, count: 1)

在此代码行的末尾,pointer立即无效。没有保证value甚至在下一行代码中也存在。我不确定您要在这里实现什么,但这绝不是安全的方法。您可能正在寻找的.withUnsafeBytes方法之一,取决于您的工作方式。


3
尽管您的答案可能是正确的,但如果您举个例子说明这样做可能会失败,那就更好了。有一些使用Unsafe * Pointer浮动的强制转换和转换的示例(stackoverflow.com/a/27456220/5276890)现在会生成此警告。
罗伊·福尔克

3

我的代码看起来几乎与您正在执行的操作相同,并且收到相同的警告。我的讨论方式略有不同

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

这仍然会产生警告,提示UnsafeBufferPointer正在产生悬空的Pointer,但是提示说“产生的指针仅在对'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)
}

并且这不会生成警告,并且似乎可以正常工作(无论如何在我的应用程序中)。它是否通过专家的认可是另一回事。

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


3

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

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

考虑到@greg的回答,我将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

这是扩展名

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

append(.init(value: value))
Leo Dabus
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.