内存安全(Memory Safety)(学习笔记)
环境Xcode 11.0 beta4 swift 5.1
欢迎留言 pen me
- 前言
- 理解内存访问冲突
- 存储器访问特性,主要有3个特性:一、访问是读还是写; 二、访问的持续时间; 三、被访问的内存位置;如果有两个访问满足以下条件将会发生冲突
- 至少有一个写访问
- 访问同一块内存
- 访问时间有重叠
读访问和写访问还是有区别的,读要改变内存而写不需要;内存访问可以是瞬时的也可是持续的,如果其它代码无法在访问开始之后且在访问结束之前运行,则访问是瞬时的
从本质上讲,瞬时访问不可能同时发生的,大多数访问是即时的。示例如下:func oneMore(than number: Int) -> Int { return number + 1 } // var myNumber = 1 myNumber = oneMore(than: myNumber) print(myNumber) // Prints "2"
有多种方法访问内存,跨度超过其它代码的执行,这叫持续访问;一个持续访问可以与其它持续访问或瞬时访问发生重叠;这种重叠主要发生在
in-out
参数 和 结构体的mutating
方法in-out
参数访问冲突示例如下
var stepSize = 1; func increment(_ number: inout Int){ number += stepSize } increment(&stepSize) // Error: conflicting access to stepSize // 此处读访问与写时有重叠,如下图
// 解决冲突的方法 // Make an explicit copy. var copyOfStepSize = stepSize increment(©OfStepSize) // Update the original. stepSize = copyOfStepSize // stepSize is Now 2
将同一个变量作为同一个函数的多个 in-out 参数传递会发生冲突
swift func balance(_ x: inout Int, _ y: inout Int) { let sum = x + y x = sum / 2 y = sum - x } var playerOnescore = 42 var playerTwoscore = 30 balance(&playerOnescore, &playerTwoscore) // OK balance(&playerOnescore, &playerOnescore) // Error: conflicting accesses to playerOnescore
- 方法内访问
self
冲突示例
struct Player { var name: String var health: Int var energy: Int static let maxHealth = 10 mutating func restoreHealth() { health = Player.maxHealth } } extension Player { mutating func shareHealth(with teammate: inout Player) { balance(&teammate.health, &health) } } // var oscar = Player(name: "Oscar", health: 10, energy: 10) var maria = Player(name: "Maria", health: 5, energy: 10) oscar.shareHealth(with: &maria) // OK 访问的内存不同,如下图 oscar.shareHealth(with: &oscar) // Error: conflicting accesses to oscar 如下下图
- 访问属性时冲突
var playerinformation = (health: 10, energy: 20) balance(&playerinformation.health, &playerinformation.energy) // Error: conflicting access to properties of playerinformation
- 访问结构体属性
var holly = Player(name: "Holly", health: 10, energy: 10) balance(&holly.health, &holly.energy) // Error // 但下面的情况是可以的,如果上面的变量 holly 是局部变量而不是全局变量,编译器可以证明这种重复访问是安全的,因为两个存储属性的内存不可能有交叉 func someFunction() { var oscar = Player(name: "Oscar", health: 10, energy: 10) balance(&oscar.health, &oscar.energy) // OK }
原文地址:https://www.cnblogs.com/tzsh1007/p/11661800.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。