【问题标题】:A memory leak, could my problem be with pointers [swift]内存泄漏,我的问题可能与指针有关吗?
【发布时间】:2019-10-05 04:14:11
【问题描述】:

iOS 12.x Swift 5

我正在使用套接字与另一个盒子通信,我编写了这段代码,我认为这很有意义。但我想咨询专家。我问是因为我认为这个应用程序存在某种内存泄漏。我怀疑指针,就像你一样。我正在观察它使用的内存在我运行时慢慢增加。

func sendMessage(message: String) {

    let data = message.data(using: String.Encoding.utf8, allowLossyConversion: false)!
    let dataMutablePointer = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count)
    //Copies the bytes to the Mutable Pointer

    dataMutablePointer.initialize(to: 0)
    data.copyBytes(to: dataMutablePointer, count: data.count)

    //Cast to regular UnsafePointer
    let dataPointer = UnsafePointer<UInt8>(dataMutablePointer)

    //Your stream
    outputStream.write(dataPointer, maxLength: data.count)
    defer {
      dataMutablePointer.deinitialize(count: data.count)
    }
}

这段代码看起来正常吗?这可能是我的内存泄漏的根源吗?我需要取消初始化这个指针吗?

【问题讨论】:

  • 您可能需要在完成后显式调用deallocate 来删除您的指针以避免内存问题。看起来您正在使用deinitializedeveloper.apple.com/documentation/swift/unsafepointer/…
  • 我可以在 defer 语句中取消分配吗?显然我不希望它在流完成之前取消分配内存。
  • 我不是确定的。但我认为你可以在dataPointerdataMutablePointer 范围内的任何地方调用它。
  • 您可以使用defer { dataMutablePointer.deallocate() },只要您希望在您离开范围时总是发生解除分配。此外,您只需要在非平凡类型上调用 deinitialize(count:),因此您可以根据需要在此上下文中删除该调用。

标签: ios swift pointers stream


【解决方案1】:

这可能是我的内存泄漏的根源吗?

是的,当然。

我需要取消初始化这个指针吗?

正如 bscothern 所评论的,如果 Pointee 是非平凡类型,则需要取消指针的初始化。但对于UInt8,则不是强制性的。

但您最终需要释放指针

你的代码应该是这样的:

func sendMessage(message: String) {

    let data = message.data(using: String.Encoding.utf8, allowLossyConversion: false)!
    let dataMutablePointer = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count)
    defer {
        dataMutablePointer.deallocate()
    }

    //Copies the bytes to the Mutable Pointer
    dataMutablePointer.initialize(to: 0)
    defer {
        //This is not required, but you can put `deinitialize` here if you prefer
        dataMutablePointer.deinitialize(count: data.count)
    }
    data.copyBytes(to: dataMutablePointer, count: data.count)

    //Cast to regular UnsafePointer
    let dataPointer = UnsafePointer<UInt8>(dataMutablePointer)

    //Your stream
    outputStream.write(dataPointer, maxLength: data.count)
}

defer 将其块的执行推迟到封闭块的末尾,因此 dataMutablePointer.deallocate() 将在 outputStream.write(dataPointer, maxLength: data.count) 完成后执行。

但我会在不复制数据的情况下写一些等效的东西:

func sendMessage(message: String) {

    let data = message.data(using: String.Encoding.utf8, allowLossyConversion: false)!

    data.withUnsafeBytes {bytes in
        let dataPointer = bytes.baseAddress!.assumingMemoryBound(to: UInt8.self)
        //Your stream
        outputStream.write(dataPointer, maxLength: data.count)
    }
}

或者,更简单地说:

func sendMessage(message: String) {
    //Your stream
    outputStream.write(message, maxLength: message.utf8.count)
}

【讨论】:

  • 感谢您花时间写这篇文章。我的解决方案是否比您的可选解决方案更线程安全,或者它们是否相同。另一端有多个进程写入流,因此理论上可以在第一条消息完成之前调用 sendMessage。
猜你喜欢
  • 2023-03-29
  • 1970-01-01
  • 2011-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多