[Swift] Memory Safety

7590 ワード

Memory Safety


デフォルトでは、SWIFTはコード内の不安全な動作を阻止します.たとえば、初期化前に変数が使用されないようにし、メモリが解放(解放)された後に変数にアクセスせず、配列内のインデックスが範囲外であるかどうかを確認します.
SWIFTは、競合を防止するために同じメモリ領域に同時にアクセスできます.SWIFTはメモリを自動的に管理できるため、メモリへのアクセスを考慮する必要はほとんどありませんが、メモリの競合が発生する可能性があることを理解することが重要です.

Understanding Conflicting Access to Memory


同時アクセスは、主にinoutパラメータの関数または構造を使用する方法または変異方法で発生する.

Conflicting Access to In-Out Parameters


For example:
var stepSize = 1

func increment(_ number: inout Int) { // write access
    number += stepSize // read access
}

increment(&stepSize)
// Error: conflicting accesses to stepSize
numberinoutパラメータなので、関数を呼び出すときはwrite accessリファレンスメモリを使用してください.
function内部では、stepSizeがメモリにアクセスして読み取りアクセスを行うが、write accessなどのメモリ位置を参照するとメモリ競合(競合)が発生する.

Conflicting Access to self in Methods


A mutating method on a structure has write access to self for the duration of the method call. For example, consider a game where each player has a health amount, which decreases when taking damage, and an energy amount, which decreases when using special abilities.
struct Player {
    var name: String
    var health: Int
    var energy: Int

    static let maxHealth = 10
    mutating func restoreHealth() {
        health = Player.maxHealth
    }
}

func balance(_ x: inout Int, _ y: inout Int) {
    let sum = x + y
    x = sum / 2
    y = sum - x
}

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
上記の例では、balance関数を呼び出すと、2つのinoutパラメータがwrite accessを使用してメモリを参照しますが、異なる場所のメモリにアクセスするため、競合は発生しません.

ただし、oscarを関数のパラメータとして渡すと、競合が発生します.
oscar.shareHealth(with: &oscar)
// Error: conflicting accesses to oscar
mutatingメソッドでは、selfの書き込みアクセスが必要です.inoutパラメータを使用してself、すなわちoscarを渡すと、同じメモリ位置が参照されるため、2つの書き込みアクセスが競合します.

Reference


Memory Safety