swift - 当使用来自另一个类实例的指针引用时,UnsafeBufferPointer 将无法工作

标签 swift swift3 swift4

我有两段代码:

// Non-working one
public func put(path: String) -> Int64 {
    owner.id += 1

    writeBatch.put(path.data(), value: Data(buffer: UnsafeBufferPointer(start: &owner.id, count: 1)))

    return owner.id
}

// Working one
public func requestId() -> Int64 {
    owner.id += 1

    return owner.id
}

public func put(path: String) -> Int64 {
    var id = requestId()

    writeBatch.put(path.data(), value: Data(buffer: UnsafeBufferPointer(start: &id, count: 1)))

    return id
}

这两段代码的区别仅在于UnsafeBufferPointer(起始参数)。诀窍是非工作版本引用另一个类实例中的值,而工作版本引用本地参数。

我不明白,为什么在这个世界上这永远行不通?我花了一个星期的时间来识别这个错误

提前致谢!

编辑

忘记说问题是什么了。该问题具有以下影响:writeBatch 收到空数据,即用零填充,而 owner.id 始终为非零。此外,该问题仅在应用程序的发布版本中重现,并且适用于开发版本

最佳答案

不能 100% 确定,但您可能会遇到 Swift 的这个功能 inout参数:

Function Declaration

In-Out Parameters

In-out parameters are passed as follows:

  1. When the function is called, the value of the argument is copied.
  2. In the body of the function, the copy is modified.
  3. When the function returns, the copy’s value is assigned to the original argument.

考虑到这种复制输入复制输出行为,请再次检查您的代码。

writeBatch.put(path.data(), value: Data(buffer: UnsafeBufferPointer(start: &owner.id, count: 1)))

调用初始化程序时 UnsafeBufferPointer.init(start:count:) , Swift 创建了 inout 的副本参数&owner.id .

然后,Swift 使用临时副本的地址调用初始化程序。

完成初始化器后,Swift 可以随时释放副本的区域,但创建的 UnsafeBufferPointer仍然持有临时区域的地址,在调用时可能不可用 Data.init .

因此 Data 的内容可以是任何意外值,但在您的情况下,它似乎全为零。


为避免此类意外结果,您不应传递 inout参数到指针的参数,可以在方法调用之后保存。

在您的情况下,一种简单的方法是使用 Data 的初始化程序直接。

请尝试这段代码,看看会发生什么:

writeBatch.put(path.data(), value: Data(bytes: &owner.id, count: MemoryLayout<Int64>.size))

初始化器 Data.init(bytes:count:)在区域释放之前复制临时区域中的内容,因此,它应该包含包含 owner.id 值的预期字节序列.


此答案的前半部分适用于您的工作。所以,这不是正确的解决方案。 (您知道一些错误的用法可能会幸运地产生预期的结果。)

关于swift - 当使用来自另一个类实例的指针引用时,UnsafeBufferPointer 将无法工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48016106/

相关文章:

ios - 如何在不同的 View Controller 中访问 Userdefault

ios - 以编程方式在swift 3中使电话崩溃

ios - CocoaPods 在添加新 pod 时出现问题

swift - 使用 Swift 包管理器时出错

swift - 'fetch' 错误的使用不明确

swift - 如何将数组数据传递给 Alamofire 中的字典

swift3 - Swift 3 中的 elementsSeparatedByString() 错误

ios - 使用 JSON swift4 中的 key 解码结构

ios - 使用 Secure Enclave iOS AES-GCM 加密/解密

objective-c - swift 错误 : Cannot convert value of type '() throws -> ()' to specified type 'Bool'