Avvertenza: l'inizializzazione di 'UnsafeBufferPointer <T>' genera un puntatore buffer pendente


10

Dopo l'aggiornamento a Swift 5.2 / Xcode 11.4 viene visualizzato un avviso al seguente codice:

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

L'inizializzazione di "UnsafeBufferPointer" genera un puntatore buffer pendente

Posso usare @silenceWarning ma è una soluzione sporca. Forse dovrei conservare il puntatore da qualche parte e pulirlo in futuro?


È strano come tutti si affrettino ad aggiornare senza preoccuparsi di leggere le note di rilascio, che sono abbastanza esplicite al riguardo.
matt

developer.apple.com/documentation/xcode_release_notes/… e cerca danling. bugs.swift.org/browse/SR-2790 sembra avere una discussione più completa su questo.
Roy Falk,

Risposte:


3

Questo non è mai stato sicuro, così felice che il team Swift lo abbia ripulito:

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

Alla fine di questa riga di codice, pointerè immediatamente non valido. Non c'è promessa che valueesista anche nella riga successiva di codice. Non sono sicuro di ciò che stavi cercando di ottenere qui, ma questo non è mai stato un modo sicuro per farlo. Quello che probabilmente stai cercando è uno dei .withUnsafeBytesmetodi, che dipende da cosa stavi lavorando.


3
Sebbene la tua risposta sia probabilmente corretta, sarebbe molto meglio se mostrassi un esempio di come ciò potrebbe non riuscire. Ci sono alcuni esempi ( stackoverflow.com/a/27456220/5276890 ) di lanci e conversioni che utilizzano Unsafe * Puntatore mobile che ora genera questo avviso.
Roy Falk,

3

Avevo un codice che sembrava quasi esattamente quello che stavi facendo e stava ricevendo lo stesso avvertimento. Il mio differiva leggermente in un modo rilevante per la discussione

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

Questo genera ancora l'avvertimento che UnsafeBufferPointer sta producendo un puntatore penzolante ma i suggerimenti dicono "produce un puntatore valido solo per la durata della chiamata a 'init (start: count :)'"

Ma il ritorno da UnsafeBufferPointer non è assegnato a nulla, quindi non ho potuto usarlo al di fuori dell'ambito dell'init se avessi provato. Quindi il compilatore qui mi sta mettendo in guardia dal fare qualcosa che non posso fare comunque.

Immagino che Data.init (buffer:) potrebbe archiviare il ptr, ma suppongo che se accetta un UnsafeBufferPointer, si accetta la responsabilità di usarlo correttamente

Comunque, ciò non risolve ancora il tuo problema. Ho aggirato l'avvertimento con questo

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

E questo non genera l'avviso e sembra funzionare (nella mia applicazione comunque). Se passa qui con gli esperti qui è un'altra questione.

Un po 'mi rende nostalgico per i giorni di HLock e HUnlock


3

Ho anche incontrato questi fastidiosi avvertimenti.

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

Considerando @ risposta di Greg, ho messo il Data.appendin withUnsafePointer's la chiusura, e non mostra più avvertimenti.

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

Ecco l'estensione

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

SECCOappend(.init(value: value))
Leo Dabus,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.