Cảnh báo: Khởi tạo 'UnsafeBufferPulum <T>' dẫn đến một con trỏ bộ đệm lơ lửng


10

Sau khi cập nhật lên Swift 5.2 / Xcode 11.4, có một cảnh báo về mã sau:

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

Trên dòng hãy để con trỏ = UnsafeBufferPulum (bắt đầu: & value, đếm: 1) Tôi đã nhận

Khởi tạo 'UnsafeBufferPulum' dẫn đến một con trỏ bộ đệm lơ lửng

Tôi có thể sử dụng @silenceWarning nhưng đó là giải pháp bẩn. Có lẽ tôi cần lưu trữ con trỏ ở đâu đó và làm sạch nó trong tương lai?


Thật kỳ lạ khi mọi người vội vàng cập nhật mà không bận tâm đọc các ghi chú phát hành, điều này khá rõ ràng về điều này.
mờ

developer.apple.com/documentation/xcode_release_notes/ Từ và tìm kiếm danling. bug.swift.org/browse/SR-2790 dường như có một cuộc thảo luận đầy đủ hơn về điều này.
Roy Falk

Câu trả lời:


3

Điều này không bao giờ an toàn, rất vui vì nhóm Swift đã dọn sạch nó:

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

Ở cuối dòng mã này, pointerngay lập tức không hợp lệ. Không có hứa hẹn rằng valuethậm chí tồn tại ở dòng mã tiếp theo. Tôi không chắc chắn những gì bạn đã cố gắng để đạt được ở đây, nhưng đây không bao giờ là một cách an toàn để làm điều đó. Những gì bạn có thể tìm kiếm là một trong những .withUnsafeBytesphương pháp, phụ thuộc vào những gì bạn đang làm việc.


3
Mặc dù câu trả lời của bạn có thể đúng, nhưng sẽ tốt hơn nhiều nếu bạn đưa ra một ví dụ về cách điều này có thể thất bại. Có một vài ví dụ ( stackoverflow.com/a/27456220/5276890 ) về việc đúc và chuyển đổi bằng cách sử dụng Con trỏ không an toàn * nổi xung quanh hiện tạo cảnh báo này.
Roy Falk

3

Tôi đã có mã trông gần như chính xác những gì bạn đang làm và nhận được cảnh báo tương tự. Của tôi khác nhau một chút theo cách có liên quan đến các cuộc thảo luận

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

Điều này vẫn tạo ra cảnh báo rằng UnsafeBufferPulum đang tạo ra một Con trỏ lơ lửng nhưng gợi ý cho biết "chỉ tạo ra một con trỏ hợp lệ trong khoảng thời gian của lệnh gọi 'init (start: Count :)'"

Nhưng lợi nhuận từ UnsafeBufferPulum không được gán cho bất cứ điều gì, vì vậy tôi không thể sử dụng nó ngoài phạm vi của init nếu tôi đã thử. Vì vậy, trình biên dịch ở đây đang cảnh báo tôi không nên làm gì đó.

Tôi đoán Data.init (bộ đệm :) có thể lưu trữ ptr, nhưng tôi sẽ cho rằng nếu nó chấp nhận UnsafeBufferPulum, thì nó chấp nhận trách nhiệm sử dụng nó đúng cách

Dù sao, điều đó vẫn không thực sự khắc phục vấn đề của bạn. Tôi đã nhận được cảnh báo với điều này

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

Và điều này không tạo ra cảnh báo và dường như hoạt động (trong ứng dụng của tôi dù sao). Cho dù nó vượt qua muster với các chuyên gia ở đây là một vấn đề khác.

Kiểu khiến tôi hoài niệm về những ngày của HLock và HUnlock


3

Tôi cũng đã gặp những cảnh báo khó chịu này.

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

Xem xét câu trả lời của @ greg, tôi đưa Data.appendvào phần withUnsafePointerđóng cửa và nó không hiển thị cảnh báo nữa.

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

Đây là phần mở rộng

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.