경고 : '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
당신의 대답은 아마 맞지만, 이것이 어떻게 실패 할 수 있는지에 대한 예를 보여 주면 훨씬 더 나을 것입니다. Unsafe * Pointer를 사용하여 캐스팅하고 변환 하는 몇 가지 예제 ( stackoverflow.com/a/27456220/5276890 )가 현재이 경고를 생성합니다.
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.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))
        }
    }
}

건조append(.init(value: value))
레오 Dabus
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.