คำเตือน: การเริ่มต้นของ '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 แต่มันเป็นโซลูชันที่สกปรก บางทีฉันอาจต้องเก็บตัวชี้ไว้ที่ไหนสักแห่งและทำความสะอาดในอนาคต?


มันแปลกที่ทุกคนรีบอัปเดตโดยไม่ต้องสนใจอ่านบันทึกประจำรุ่นซึ่งค่อนข้างชัดเจนเกี่ยวกับเรื่องนี้
แมตต์

developer.apple.com/documentation/xcode_release_notes/…และค้นหา danling bugs.swift.org/browse/SR-2790ดูเหมือนจะมีการสนทนาที่สมบูรณ์มากขึ้น
Roy Falk

คำตอบ:


3

มันไม่เคยปลอดภัยเลยดีใจที่ทีม Swift ทำความสะอาดแล้ว:

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

ในตอนท้ายของรหัสบรรทัดนี้pointerไม่ถูกต้องในทันที ไม่มีสัญญาว่าvalueแม้จะมีอยู่ในบรรทัดถัดไปของรหัส ฉันไม่แน่ใจว่าคุณกำลังพยายามทำอะไรที่นี่ แต่นี่ไม่เคยเป็นวิธีที่ปลอดภัยที่จะทำ สิ่งที่คุณกำลังมองหาคือ.withUnsafeBytesวิธีการหนึ่งซึ่งขึ้นอยู่กับสิ่งที่คุณกำลังทำอยู่


3
ในขณะที่คำตอบของคุณอาจถูกต้องมันจะดีกว่ามากถ้าคุณแสดงตัวอย่างของสิ่งนี้อาจล้มเหลว มีบางตัวอย่าง ( stackoverflow.com/a/27456220/5276890 ) ของการหล่อและการแปลงโดยใช้ Unsafe * ตัวชี้ที่ลอยอยู่รอบ ๆ ซึ่งตอนนี้สร้างคำเตือนนี้
Roy Falk

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

DRYappend(.init(value: value))
Leo Dabus
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.