Предупреждение: Инициализация UnsafeBufferPointer <T>приводит к зависанию указателя буфера - PullRequest
10 голосов
/ 26 марта 2020

После обновления до 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) }
    }
}

On line let pointer = UnsafeBufferPointer (start: & value, count: 1) Я получил

Инициализация UnsafeBufferPointer приводит к зависанию указателя буфера

Я могу использовать @silenceWarning, но это грязное решение. Может быть, мне нужно где-то хранить указатель и очистить его в будущем?

Ответы [ 3 ]

3 голосов
/ 31 марта 2020

У меня был код, который выглядел почти точно, что вы делали, и получал то же предупреждение. Мои отличия немного отличались в отношении, который имеет отношение к обсуждению '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)
}

И это не генерирует предупреждение и, кажется, работает (в любом случае, в моем приложении). Вопрос о том, проходит ли это экспертизу, - другой вопрос.

В некотором роде я испытываю ностальгию c по дням Хлока и Хэнлока

3 голосов
/ 08 апреля 2020

Я также встречал эти досадные предупреждения.

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))
        }
    }
}
3 голосов
/ 26 марта 2020

Это никогда не было безопасным, поэтому рад, что команда Swift исправила его:

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

В конце этой строки кода, pointer немедленно становится недействительным. Не обещается, что value даже существует в следующей строке кода. Я не уверен, чего вы пытались достичь здесь, но это никогда не было безопасным способом сделать это. Вероятно, вы ищете один из методов .withUnsafeBytes, который зависит от того, над чем вы работали.

...