警告: '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) }
    }
}

オンラインletポインター= UnsafeBufferPointer(start:&value、count:1)私は得ました

「UnsafeBufferPointer」を初期化すると、ダングリングバッファーポインターが発生します

@silenceWarningを使用できますが、それは汚いソリューションです。多分私はどこかにポインターを保存して将来それをきれいにする必要がありますか?


誰もがリリースノートを読まなくても更新を急いでいるのは奇妙です。
マット

developer.apple.com/documentation/xcode_release_notes/…そしてdanlingを検索してください。bugs.swift.org/browse/SR-2790はこれについてより完全な議論があるようです。
ロイフォーク

回答:


3

これは決して安全ではなかったので、Swiftチームがクリーンアップしたことをうれしく思います。

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

このコード行の終わりでpointerは、はすぐに無効になります。valueコードの次の行にも存在するという約束はありません。あなたがここで何を達成しようとしているかはわかりませんが、これは安全な方法ではありませんでした。あなたが探している可能性が高いのは、.withUnsafeBytes作業中の方法に応じた方法の1つです。


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がぶら下がりポインタを生成しているという警告をまだ生成しますが、ヒントは、「 '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)) 

グレッグの答え@考えると、私が入れData.appendwithUnsafePointerの閉鎖、それはもう、警告は表示されません。

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

DRYappend(.init(value: value))
レオダバス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.