メモリのセキュリティ(安全メモリー)(研究ノート)
環境Xcodeの11.0 beta4のSWIFT 5.1
のウェルカムメッセージのペンの私
- 序文
- デフォルトでは、スウィフトは、例えば、あなたのコード内の不安全行動を防ぐことができます:変数は、初期化する前に使用していなかった、メモリアクセスは、配列のインデックス境界がエラーをチェックし、破壊されない。スウィフトはまた、コードがメモリ内の値を変更したときにことを確認してくださいこれは、それがなりません競合する場合、同じメモリへの複数の同時アクセスを確保するために排他的になります。スウィフト自動メモリ管理なので、ほとんどの時間は、メモリアクセスを心配する必要はありません。しかし、潜在的なメモリの競合を理解することは、あなたがコードを書く避けることができるように重要であり、コードが競合が含まれている場合、エラーがコンパイルまたは実行時に発生します。
- メモリアクセス違反を理解します
以下は、メモリの読み取りと書き込みされています
// write memory var one = 1 // read memory print("We'er number \(one)!")
- メモリ競合が同じメモリにアクセスするコードの異なる部分で起こり得ることは、問題を説明するための図後の間の前、発生します
- 前と後に正しい答えを得るために国賓訪問
- 項目を追加、合計価格はこの時間のアクセス時に状態が変化するのに十分な時間が正しい答えを得られないかもしれない可能性があり際に、過渡的な状態です
時にはそこ違反を修正するには、いくつかの方法があり、ニーズが何であるかを把握するために修理する前に、例えば、この場合には、5または300を訪問することです
- メモリアクセス特性、三つの主要な特性があります:まず、アクセスが読み取りまたは書き込みであり、第二に、訪問の期間;第三に、アクセスされているメモリ位置は、2つのアクセスが出会うがある場合は、次の基準が競合します
- 少なくとも書き込みアクセスがあります。
- 同じメモリにアクセス
- アクセス時間の重なり
読み取りと書き込みアクセスは、メモリの読み取りと書き込みを変更するには、やはり違いである必要はありません。メモリアクセスは一時的でなく、永続的にすることができ、訪問が始まった後に、他のコードは、訪問の終了前に実行することはできません場合は、アクセスが瞬間的です
基本的に、瞬間的なアクセスが同時に発生することはできませんが、ほとんどのアクセスは即時です。例としては、次のとおりです: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
同様にアウトパラメータ転送の複数の関数として、同じ変数が衝突することができ
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 }
- 場合は、以下の点、SWIFTコンパイラはリピート訪問構造が安全な財産であることを保証することができます
- それだけでメモリの属性、および属性の計算がないアクセスタイプ属性を行います
- 構造体変数はローカル変数、グローバル変数でないです
- 構造もキャプチャエスケープキャプチャ閉鎖の非閉鎖でもありません