Uyarı: 'UnsafeBufferPointer <T>' nin başlatılması, sarkan bir arabellek işaretçisiyle sonuçlanır


10

Swift 5.2 / Xcode 11.4 güncellemesinden sonra aşağıdaki koda bir uyarı geldi:

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) Anladım

'UnsafeBufferPointer' öğesinin başlatılması, sarkan bir arabellek işaretçisiyle sonuçlanır

@SilenceWarning kullanabilirim ama kirli bir çözüm. Belki işaretçiyi bir yerde saklamam ve gelecekte temizlemem gerekiyor?


Herkes bu konuda oldukça açık olan sürüm notlarını okumak için uğraşmadan güncellemek için acele ediyor.
matt

developer.apple.com/documentation/xcode_release_notes/… ve danling'i arayın. bugs.swift.org/browse/SR-2790 , bunun hakkında daha kapsamlı bir tartışmaya sahip gibi görünüyor.
Roy Falk

Yanıtlar:


3

Bu hiçbir zaman güvenli değildi, Swift ekibinin temizlediği için çok mutluydu:

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

Bu kod satırının sonunda pointer, hemen geçersizdir. Bir valuesonraki kod satırında bile vaat edilemez . Burada neyi başarmaya çalıştığınızdan emin değilim, ama bu asla bunu yapmanın güvenli bir yolu değildi. Muhtemelen aradığınız şey .withUnsafeBytes, üzerinde çalıştığınız şeye bağlı olan yöntemlerden biridir .


3
Cevabınız muhtemelen doğru olsa da, bunun nasıl başarısız olabileceğine dair bir örnek göstermeniz daha iyi olurdu. Güvenli olmayan * İşaretçi kullanan döküm ve dönüşümlerin birkaç örneği ( stackoverflow.com/a/27456220/5276890 ) şimdi bu uyarıyı üretiyor.
Roy Falk

3

Neredeyse tam olarak ne yaptığını görünüyordu ve aynı uyarıyı alıyordu kod vardı. Benimki tartışma ile ilgili bir şekilde biraz farklıydı

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

Bu hala UnsafeBufferPointer'ın sarkan bir İşaretçi ürettiği uyarısını oluşturur, ancak ipuçları "yalnızca init (start: count :) '' çağrısı süresince geçerli bir işaretçi üretir" der.

Ama UnsafeBufferPointer dönüşü hiçbir şeye atanmamış, bu yüzden denedim, init kapsamı dışında kullanamazdım. Buradaki derleyici beni zaten yapamayacağım bir şey yapmaya karşı uyarıyor.

Data.init (buffer:) ptr depolamak olabilir, ama bir UnsafeBufferPointer kabul ederse, düzgün kullanma sorumluluğunu kabul varsayalım

Her neyse, bu hala probleminizi çözmez. Bununla uyarıyı aldım

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

Ve bu uyarı oluşturmaz ve (zaten benim uygulamada) çalışıyor gibi görünüyor. Buradaki uzmanlarla bir araya gelip gelmeyeceği başka bir konudur.

HLock ve HUnlock günlerinde beni nostaljik yapıyor


3

Bu sinir bozucu uyarıları da gördüm.

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'in cevap @ göz önüne alındığında, ben koymak Data.appendiçine withUnsafePointer'ın kapatılması, ve artık uyarıları göstermez.

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

İşte uzantısı

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

KURUappend(.init(value: value))
Leo Dabus
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.