美文网首页
Swift 的内存安全

Swift 的内存安全

作者: KeenV | 来源:发表于2017-11-12 00:32 被阅读0次
内存访问的特点

如果有两个访问动作出现在以下情况中,便会发生冲突

  1. 至少有一个动作是写入访问
  2. 访问的是同一块内存
  3. 访问的时间有重叠

访问内存分为即时的和长期的

  1. 即时的访问:如果其它代码在访问开始之后至结束之前无法运行,则访问是即时的。 所以,两个即时访问不能同时发生。 大部分内存访问是即时的。
以下所有的访问都是即时的
func oneMore(than number: Int) -> Int {
    return number + 1
}
 
var myNumber = 1
myNumber = oneMore(than: myNumber)
print(myNumber)
// Prints "2"
  1. 长期的访问:其它代码可能在访问开始之后至结束之前运行,称为重叠(overlap),一个长期访问可以和另一个长期访问或即时访问重叠。

重叠访问:主要出现在函数的in-out参数和结构中的方法和可变方法中。

in-out参数的访问冲突

函数对它的in-out参数有写入的长期访问

不能对传递给in-out参数的变量有任何的访问,否则会产生冲突

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

不能把同一个变量传递给同一函数的不同in-out参数,否则会产生冲突

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)
方法内self的访问冲突

一个可变方法调用时对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给参数时,会产生冲突
oscar.shareHealth(with: &oscar)
image.png
属性的访问冲突

结构体、元组和枚举的都是值类型,对类型中的值改变会改变整个值,所以对一个属性的读取或写入访问需要读取或写入访问整个值。

把变量传递给in-out参数,会在整个函数调用期间对变量有写入的访问,
下列例子对元组有两个定入的访问,所以会产生冲突。
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
编译器会保证局部的结构体变量的重叠是安全的
func someFunction() {
    var oscar = Player(name: "Oscar", health: 10, energy: 10)
    balance(&oscar.health, &oscar.energy)  // OK
}

满足以下条件的重叠是安全的

  1. 仅仅访问的实例的存储性属性,没有计算性属性和类属性
  2. 结构体是局部变量,不是全局变量
  3. 结构体要么不被闭包捕获,要么只能被nonescaping闭包捕获。
    原文地址

相关文章

  • swift 内存安全

    Swift 会阻止你代码里不安全的行为。例如,Swift 会保证变量在使用之前就完成初始化,在内存被回收之后就无法...

  • Swift - 内存安全

    内存安全 默认情况下,Swift 会阻止你代码里不安全的行为。例如,Swift 会保证变量在使用之前就完成初始化,...

  • Swift 的内存安全

    内存访问的特点 如果有两个访问动作出现在以下情况中,便会发生冲突 至少有一个动作是写入访问 访问的是同一块内存 访...

  • [Swift] 指针UnsafePointer

    本文系学习Swift中的指针操作详解的整理 默认情况下Swift是内存安全的,苹果官方不鼓励我们直接操作内存。但是...

  • 常见的crash原因

    确定崩溃是否是Swift Runtime错误 Swift使用内存安全技术来及早发现编程错误。如果Swift运行时遇...

  • 25、【Swift】内存安全

    Swift 安全性使用前就初始化内存在变量释放后不能再访问数组会检查越界错误 Swift 还通过要求标记内存位置来...

  • Swift编程二十六(内存安全)

    案例代码下载 内存安全 默认情况下,Swift可以防止代码中发生不安全行为。例如,Swift确保变量在使用之前进行...

  • 《Swift从入门到精通》(二十二):内存安全

    内存安全(Memory Safety)(学习笔记) 环境Xcode 11.0 beta4 swift 5.1欢迎留...

  • Swift 4.2基础 ---Swift 内存安全

    默认情况下,Swift可以防止代码中出现不安全行为。例如,Swift确保变量在使用之前被初始化,内存在被释放后不被...

  • Swift5.2 拾遗笔记(四)

    本文为私人学习笔记,仅仅做为记录使用,详情内容请查阅 中文官方文档。 内存安全 Swift 自动管理内存,大部分时...

网友评论

      本文标题:Swift 的内存安全

      本文链接:https://www.haomeiwen.com/subject/zoowmxtx.html