【问题标题】:Initialization of 'UnsafePointer<UInt8>' results in a dangling pointer'UnsafePointer<UInt8>' 的初始化导致指针悬空
【发布时间】:2020-10-18 10:20:53
【问题描述】:

试图清除我的 SWIFT 5/XCODE 项目中的一些警告,但我被困在了这个:

 let sendBytes:[UInt8] = [0x0, 0x0, 0x5, 0x0]
 let msgData = Data(bytes: UnsafePointer<UInt8>(sendBytes), count: sendBytes.count)
 socket.write(msgData, withTimeout: -1.0, tag: 0)
 socket.readData(withTimeout: -1.0, tag: 0)
        

对于“UnsafePointer”,我收到以下警告和两条建议:

“UnsafePointer”的初始化导致指针悬空

  1. 从 '[UInt8]' 到 'UnsafePointer' 的隐式参数转换会生成一个仅在调用 'init(_:)' 期间有效的指针

  2. 在 Array 上使用 'withUnsafeBufferPointer' 方法,以便将参数显式转换为对定义范围有效的缓冲区指针

这是我的解决方案,更好吗?

版本 1:

let sendBytes:[UInt8] = [0x0, 0x0, 0x5, 0x0]
let uint8Pointer = UnsafeMutablePointer<UInt8>.allocate(capacity: sendBytes.count)
uint8Pointer.initialize(from: sendBytes, count: sendBytes.count)
let msgData = Data(bytes: uint8Pointer, count: sendBytes.count)
socket.write(msgData, withTimeout: -1.0, tag: 0)
socket.readData(withTimeout: -1.0, tag: 0)

版本 2:

let sendBytes:[UInt8] = [0x0, 0x0, 0x5, 0x0]                     
let uint8Pointer = UnsafeMutablePointer<UInt8>.allocate(capacity: sendBytes.count)
uint8Pointer.initialize(from: sendBytes, count: sendBytes.count)
let msgData = Data(bytes: uint8Pointer, count: sendBytes.count)
socket.write(msgData, withTimeout: -1.0, tag: 0)
socket.readData(withTimeout: -1.0, tag: 0)
uint8Pointer.deallocate()

【问题讨论】:

  • 您是在问为什么会收到此警告或如何解决?对于前者(如果不清楚),当这个函数(大概是init)返回时,sendBytes 将被释放。此时,它的UnsafePointer 不再有效(它指向已释放的内存),因此如果msgData 稍后尝试使用它,将导致“不良”行为。
  • 嗨,亚历克斯——我在上面添加了我的解决方案——这是更好的处理方式吗?
  • 这确实解决了范围问题,但现在您将遇到内存泄漏,除非您在 ptr 上手动调用 deallocate(在使用完成之后)。来自文档:“您有责任通过不安全的指针处理您使用的任何内存的生命周期,以避免泄漏或未定义的行为。”
  • 知道了!我在上面添加了第 2 版——在我发送字节后我解除了指针的分配。
  • 如果不确切知道socket.write 做了什么,就不可能肯定地说(例如,如果它将ptr 存储在全局变量中并稍后尝试访问它,这将中断);但假设它只是写入数据,那么看起来不错。如果这就是您使用msgData 的方式,那么您的原始代码可能也很好(因为msgData 仅在超出范围之前使用)

标签: swift xcode swift5


【解决方案1】:

从 Swift 3 开始,可以简单地使用 UInt8 数组初始化 Data 实例。

let sendBytes:[UInt8] = [0x0, 0x0, 0x5, 0x0]
let msgData = Data(sendBytes)

【讨论】:

  • 砰!这行得通——这是非常旧的代码,只需删除“UnsafePointer”即可删除 XCODE 中的警告。
  • 我喜欢这样的答案