gpt4 book ai didi

swift - Swift 中 “+=” 运算符的内存安全

转载 作者:可可西里 更新时间:2023-11-01 00:55:28 26 4
gpt4 key购买 nike

我一直在学习swift,遇到一个关于内存安全的问题。 += 运算符在左侧采用一个 inout 参数,该参数应该对整个函数调用具有写访问权限。它在其实现中执行类似 left = right+left 的操作。这似乎是写入和读取访问的重叠。这怎么不违反内存安全?

编辑:根据The Swift Programming Language ,它可以在单个线程中发生:

However, the conflicting access discussed here can happen on a single thread and doesn’t involve concurrent or multi-threaded code.

详述:以下是 The Swift Programming Language(Swift 4.1 beta)中的两个示例。我很困惑这个自定义 += 实现是如何在结构 Vector2D 中实现的没关系:

static func += (left: inout Vector2D, right: Vector2D) {
left = left + right
}

如果不是:

var stepSize = 1
func incrementInPlace(_ number: inout Int) {
number += stepSize
}
incrementInPlace(&stepSize)
// Error: conflicting accesses to stepSize

进一步编辑:

我认为我的问题确实是 += 作为一个 func,特别是在使用时

stepSize += stepSize

或自定义实现:

var vector = Vector2D(x: 3.0, y: 1.0)
vector += vector

这没有任何错误。但是 func 从左边获取一个 inout,因此对“step”有一个长期的写访问权限,然后如果右边也传入了“step”,我很困惑这怎么不是对“step”的即时读取访问”与“step”的长期写作重叠。还是仅当您为两个 inout 参数传递同一实例而不是一个 inout 和一个常规参数时才会出现问题?

最佳答案

我知道你已经明白了,但要为 future 的读者澄清一下;在您的评论中,您说:

... it is, in the end, a problem with any one-line code changing self by reading self first.

不,仅此还不够。作为Memory Safety本章说,这个问题只有在以下情况下才会出现:

  • At least one is a write access.
  • They access the same location in memory.
  • Their durations overlap.

考虑:

var foo = 41
foo = foo + 1

foo = foo + 1 不是问题(foo += 1 也不会;foo += foo 也不会)因为构成了一系列“瞬时”访问。因此,尽管我们(用你的话来说)“通过先阅读自己来改变自己的代码”,但这不是问题,因为它们的持续时间不重叠。

只有当您处理“长期”访问时,问题才会显现出来。那样guide继续说:

A function has long-term write access to all of its in-out parameters. The write access for an in-out parameter starts after all of the non-in-out parameters have been evaluated and lasts for the entire duration of that function call. If there are multiple in-out parameters, the write accesses start in the same order as the parameters appear.

One consequence of this long-term write access is that you can’t access the original variable that was passed as in-out, even if scoping rules and access control would otherwise permit it—any access to the original creates a conflict.

那么,考虑你的第二个例子:

var stepSize = 1
func incrementInPlace(_ number: inout Int) {
number += stepSize
}
incrementInPlace(&stepSize)

在这种情况下,您可以长期访问任何 number 引用。当您使用 &stepSize 调用它时,这意味着您可以长期访问与 stepSize 关联的内存,因此 number += stepSize 意味着您尝试访问 stepSize 而您已经可以长期访问它。

关于swift - Swift 中 “+=” 运算符的内存安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49832784/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com