Skip to content

Latest commit

ย 

History

History
234 lines (167 loc) ยท 11 KB

memorySafety.md

File metadata and controls

234 lines (167 loc) ยท 11 KB

Memory Safety

์Šค์œ„ํ”„ํŠธ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ฝ”๋“œ์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” unsafeํ•œ ๋™์ž‘๋“ค์„ ๋ฐฉ์ง€ ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ณ€์ˆ˜๊ฐ€ ์ดˆ๊ธฐํ™” ๋˜์–ด์•ผ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ deallocated ๋˜๊ธฐ์ „์— ์ ‘๊ทผ์ด ์•ˆ๋˜๊ณ , ๋ฐฐ์—ด์—์„œ indece๊ฐ€ out-of-bounds ์—๋Ÿฌ๊ฐ€ ๋‚˜๋Š”์ง€ ์ฒดํฌํ•ด์ค€๋‹ค. ์Šค์œ„ํ”„ํŠธ๋Š” ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ ‘๊ทผ์ด ํ•œ ๋ฉ”๋ชจ๋ฆฌ ์ง€์—ญ์„ ์ ‘๊ทผํ•˜๋”๋ผ๋„ ์ฝ”๋“œ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์— ๋ฐฐํƒ€์ ์œผ๋กœ ์ ‘๊ทผํ•˜๊ฒŒํ•จ์œผ๋กœ์จ ๋ฉ”๋ชจ๋ฆฌ ์ถฉ๋Œ์ด ์ผ์–ด๋‚˜์ง€ ์•Š๋„๋ก ํ•œ๋‹ค. ์Šค์œ„ํ”„ํŠธ๋Š” ์ž๋™์ ์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋ฅผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ๋ฉ”๋ชจ๋ฆฌ์— ๋Œ€ํ•ด ์‹ ๊ฒฝ ์“ธ ํ•„์š”๊ฐ€ ์—†๋‹ค. ์ฝ”๋“œ ๋‚ด์— ์ถฉ๋Œ์ด ์žˆ๋‹ค๋ฉด, ์ปดํŒŒ์ผ ํƒ€์ž„์ด๋‚˜ ๋Ÿฐํƒ€์ž„์— ์—๋Ÿฌ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

Understanding Conflicting Access to Memory

๋ณ€์ˆ˜์— ๊ฐ’์„ ์ง€์ •ํ•˜๊ฑฐ๋‚˜ ํ•จ์ˆ˜์— ์ธ์ž๋ฅผ ๋„˜๊ฒจ์ค„ ๋•Œ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ์ด ์ผ์–ด๋‚œ๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด, ๋‹ค์Œ ์ฝ”๋“œ์—์„œ๋Š” ์ฝ๊ธฐ, ์“ฐ๊ธฐ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ์ด ์ผ์–ด๋‚œ๋‹ค.

// A write access to the memory where one is stored.
var one = 1

// A read access from the memory where one is stored.
print("We're number \(one)!")

๋‹ค๋ฅธ ์ฝ”๋“œ์—์„œ ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ location์— ๋™์‹œ์— ์ ‘๊ทผํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ์ถฉ๋Œ์ด ์ผ์–ด๋‚  ์ˆ˜ ์žˆ๋‹ค. ํ•œ ๋ฉ”๋ชจ๋ฆฌ location์— ์—ฌ๋Ÿฌ ์ ‘๊ทผ์„ ํ•œ๋‹ค๋ฉด ์˜ˆ์ƒํ•  ์ˆ˜ ์—†๋Š”, ์ผ๊ด€์ ์ด์ง€ ์•Š์€ ๋™์ž‘์ด ์ผ์–ด๋‚  ์ˆ˜ ์žˆ๋‹ค. ์Šค์œ„ํ”„ํŠธ์—์„œ๋Š”, ํ•˜๋‚˜์˜ ๊ฐ’์„ ๋ฐ”๊พธ๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ์ค„์˜ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋Š”๋ฐ ์ด ์‹œ๊ฐ„๋™์•ˆ ๊ฐ™์€ ๊ฐ’์„ ์ ‘๊ทผํ•˜๋ ค๋Š” ์‹œ๋„๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.

๊ฐ€๊ณ„๋ถ€๋กœ ๋น—๋Œ„ ๋ฉ”๋ชจ๋ฆฌ ์ถฉ๋Œ ์„ค๋ช…

  • ๊ฐ€๊ณ„๋ถ€ ์ˆ˜์ •์ค‘์— Total์— ์ ‘๊ทผํ•œ๋‹ค๋ฉด ์‹œ๊ธฐ์— ๋”ฐ๋ผ์„œ ๋‹ค๋ฅธ ๊ฐ’์„ ์–ป์„ ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.

NOTE ๋งŒ์•ฝ concurrent๋‚˜ multithreade code๋ฅผ ์ž‘์„ฑํ•ด ๋ณธ์ ์ด ์žˆ๋‹ค๋ฉด ์ด๋Ÿฐ ๋ฉ”๋ชจ๋ฆฌ ์ถฉ๋Œ์— ์ต์ˆ™ํ•  ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ฉ”๋ชจ๋ฆฌ ์ถฉ๋Œ์ด concurrent๋‚˜ multithreade ์ฝ”๋“œ๊ฐ€ ์•„๋‹ˆ๋”๋ผ๋„ single thread์—์„œ๋„ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ๋งŒ์•ฝ ์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ์—์„œ ๋ฉ”๋ชจ๋ฆฌ ์ถฉ๋Œ์„ ๊ฒช๋Š”๋‹ค๋ฉด, ์Šค์œ„ํ”„ํŠธ์—์„œ๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„์ด๋‚˜ ๋Ÿฐํƒ€์ž„์—์„œ ์—๋Ÿฌ ๋ฉ”์„ธ์ง€๋ฅผ ๋ฐ›์•„๋ณผ ์ˆ˜์žˆ๋‹ค.(์—๋Ÿฌ๋ฉ”์„ธ์ง€ ์—†์ด ์—๋Ÿฌ๊ฐ€ ๋‚˜์ง€๋Š” ์•Š์„ ๊ฑฐ๋ผ๋Š” ๋œป์ธ๋“ฏ) multithreaded ์ฝ”๋“œ์—์„œ "Thread Sanitizer๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด thread๋ฅผ ๋„˜๋‚˜๋“œ๋Š” ๋ฉ”๋ชจ๋ฆฌ ์ถฉ๋Œ์„ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค."

๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ์˜ ํŠน์ง•

๋ฉ”๋ชจ๋ฆฌ ์ถฉ๋Œ์„ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ์˜ 3๊ฐ€์ง€ ํŠน์ง•์„ ์•Œ ํ•„์š”๊ฐ€ ์žˆ๋‹ค.

  1. ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ฝ๊ธฐ ์ ‘๊ทผ์ธ์ง€ ์“ฐ๊ธฐ ์ ‘๊ทผ์ธ์ง€
  2. ์ ‘๊ทผ ์‹œ๊ฐ„
  3. ์ ‘๊ทผ๋˜๋Š” ๋ฉ”๋ชจ๋ฆฌ location

ํŠนํžˆ, ๋‹ค์Œ ์ƒํ™ฉ์„ ๋ชจ๋‘ ๋งŒ์กฑ์‹œํ‚ค๋Š” 2๊ฐ€์ง€ ์ ‘๊ทผ์ด ์ผ์–ด๋‚œ๋‹ค๋ฉด ๋ฉ”๋ชจ๋ฆฌ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์“ฐ๊ธฐ ์ ‘๊ทผ์ด๊ฑฐ๋‚˜ nonatomic ์ ‘๊ทผ ์ค‘ ํ•˜๋‚˜๋ฅผ ๋งŒ์กฑ

  • ์ ‘๊ทผ๋“ค์ด ํ•œ๊ฐ€์ง€ ์ง€์—ญ์„ ์ ‘๊ทผ

  • ์ ‘๊ทผ ์‹œ๊ฐ„์ด ์„œ๋กœ ๊ฒน์นจ

์ฝ๊ธฐ์™€ ์“ฐ๊ธฐ ์ ‘๊ทผ์˜ ์ฐจ์ด๋Š” ๋ช…ํ™•ํ•œ๋ฐ ์“ฐ๊ธฐ ์ ‘๊ทผ์€ ํ•ด๋‹น ๋ฉ”๋ชจ๋ฆฌ ์ง€์—ญ์„ ๋ฐ”๊พผ๋‹ค.(์ฝ๊ธฐ ์ ‘๊ทผ์€ ๋ฐ”๊พธ์ง€ ์•Š์Œ) ๋ฉ”๋ชจ๋ฆฌ ์ง€์—ญ(location in memory)๋Š” ๋ฌด์—‡์ด ์ ‘๊ทผ๋  ์ง€๋ฅผ ๋œปํ•œ๋‹ค.(์˜ˆ๋ฅผ ๋“ค์–ด, ๋ณ€์ˆ˜, ์ƒ์ˆ˜, property)

๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ ์‹œ๊ฐ„์€ ์ˆœ๊ฐ„์ ์ด๊ฑฐ๋‚˜(instantaneous) long-term์ผ ์ˆ˜ ์žˆ๋‹ค.

์•„ํ† ๋ฏน ์˜คํผ๋ ˆ์ด์…˜์ด๋ž€ C ์•„ํ† ๋ฏน ์˜คํผ๋ ˆ์ด์…˜์„ ๋œปํ•œ๋‹ค. C ์•„ํ† ๋ฏน ์˜คํผ๋ ˆ์ด์…˜์˜ ๋ชฉ๋ก์„ ๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด stdatomic(3) ๋ฉ”๋‰ด์–ผ ํŽ˜์ด์ง€๋ฅผ ์ฐธ๊ณ 

์ ‘๊ทผ์ด ์ˆœ๊ฐ„์ (instantaneous)ํ•˜๋‹ค๋Š” ๊ฒƒ์€ ํ•ด๋‹น์ ‘๊ทผ ๋๋‚ ๋•Œ๊นŒ์ง€ ๋‹ค๋ฅธ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š์Œ์„ ๋œปํ•œ๋‹ค. ๋”ฐ๋ผ์„œ 2๊ฐœ์˜ ์ˆœ๊ฐ„์ (instantaneous)ํ•œ ์ฝ”๋“œ๋Š” ๋™์‹œ์— ์‹คํ–‰๋  ์ˆ˜ ์—†๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ์€ ์ˆœ๊ฐ„์ (instantaneous)ํ•˜๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด ์•„๋ž˜ ์ฝ”๋“œ์—์„œ์˜ ์ฝ๊ธฐ ์ ‘๊ทผ๊ณผ ์“ฐ๊ธฐ ์ ‘๊ทผ์€ ์ „๋ถ€ instantaneousํ•ฉ๋‹ˆ๋‹ค.

func oneMore(than number: Int) -> Int {
    return number + 1
}

var myNumber = 1
myNumber = oneMore(than: myNumber)
print(myNumber)
// Prints "2"

๋กฑํ…€ ์ ‘๊ทผ์€ ๋‹ค๋ฅธ ๋กฑํ…€ ์ ‘๊ทผ๋‚˜ instantaneous์ ‘๊ทผ ์ฝ”๋“œ์™€ ์‹œ๊ฐ„์ด ์ค‘์ฒฉ๋  ์ˆ˜ ์žˆ๋‹ค.

์ค‘์ฒฉ๋˜๋Š” ์ ‘๊ทผ์ด ์ฃผ๋กœ ์ผ์–ด๋‚˜๋Š” ์ฝ”๋“œ๋Š” "ํ•จ์ˆ˜๋‚˜ ๋ฉ”์„œ๋“œ์—์„œ in-out ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉ"ํ•˜๊ฑฐ๋‚˜ "์ŠคํŠธ๋ŸญํŠธ์—์„œ mutating ๋ฉ”์†Œ๋“œ"๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์ด์ œ ํ•˜๋‚˜์”ฉ ์‚ดํŽด๋ณด์ž

Conflicting Access to In-Out Parameters

ํ•จ์ˆ˜๋Š” ๋ชจ๋“  in-out parameter์— ๋Œ€ํ•ด ๋กฑํ…€ write access ๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค.

in-out ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋Œ€ํ•œ ์“ฐ๊ธฐ ์ ‘๊ทผ์€ ๋ชจ๋“  non-in-outํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ evaluated ๋œ ๋’ค๋ถ€ํ„ฐ ํ•จ์ˆ˜์˜ ํ˜ธ์ถœ์ด ๋๋‚ ๋•Œ๊นŒ์ง€ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ์— ์—ฌ๋Ÿฌ๊ฐœ์˜ in-out ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์žˆ๋‹ค๋ฉด ํŒŒ๋ผ๋ฏธํ„ฐ์— ์“ฐ์—ฌ์žˆ๋Š” ์ˆœ์„œ๋Œ€๋กœ ์“ฐ๊ธฐ ์ ‘๊ทผ์ด ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค.

๋กฑํ…€ ์“ฐ๊ธฐ ์ ‘๊ทผ์œผ๋กœ ์ธํ•œ ์“ฐ๊ธฐ ์„œ in-outํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜์–ด์˜จ ๊ฐ’์˜ ์˜ค๋ฆฌ์ง€๋„ ๊ฐ’์„ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋‹ค.

var stepSize = 1

func increment(_ number: inout Int) {
    number += stepSize
}

increment(&stepSize)
// Error: conflicting accesses to stepSize
  • ์œ„ ์ฝ”๋“œ์—์„œ ํ•จ์ˆ˜๋กœ ๋„˜์–ด์˜จ inout parameter์— ๋Œ€ํ•ด ์“ฐ๊ธฐ ์ ‘๊ทผ์ด ์‹œ์ž‘๋˜๋Š”๋ฐ ํ•จ์ˆ˜๋‚ด๋ถ€์—์„œ stepsize์— ๋Œ€ํ•œ ์ฝ๊ธฐ ์ ‘๊ทผ์ด ์ผ์–ด๋‚˜๋ฏ€๋กœ ๊ฐ ์ ‘๊ทผ์ด ์ค‘์ฒฉ๋˜๋ฏ€๋กœ ์ถฉ๋Œ์ด ์ผ์–ด๋‚ฉ๋‹ˆ๋‹ค.

์ด ์ถฉ๋Œ์„ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€ stepSize๋ฅผ ๋ณต์‚ฌํ•ด๋ฒ„๋ฆฌ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

// Make an explicit copy.
var copyOfStepSize = stepSize
increment(&copyOfStepSize)

// Update the original.
stepSize = copyOfStepSize
// stepSize is now 2

์ด๋ ‡๊ฒŒ ๋˜๋ฉด ์“ฐ๊ธฐ์ ‘๊ทผ์ด ์‹œ์ž‘๋˜๊ธฐ ์ „์— ์ฝ๊ธฐ ์ ‘๊ทผ์ด ๋๋‚˜๊ธฐ ๋•Œ๋ฌธ์— ์ถฉ๋Œ์ด ์ผ์–ด๋‚˜์ง€ ์•Š๋Š”๋‹ค.

๋‹ค๋ฅธ ๋ฌธ์ œ์ ์œผ๋กœ๋Š” ์—ฌ๋Ÿฌ๊ฐœ์˜ in-output ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ํ•˜๋‚˜์˜ ๊ฐ’์„ ๋„˜๊ธฐ๋ฉด ์ถฉ๋Œ์ด ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค. For example:

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

๋‹ค๋ฅธ ์ธ์ž ๋ฉ”๋ชจ๋ฆฌ ์œ„์น˜์— ์ ‘๊ทผํ•˜๋Š” ์ฒซ๋ฒˆ์งธ ๊ฒฝ์šฐ ์‹œ๊ฐ„์ด ์ค‘์ฒฉ๋˜์ง€๋งŒ ์ ‘๊ทผํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ์œ„์น˜๊ฐ€ ๋‹ค๋ฅด๊ธฐ๋•Œ๋ฌธ์— ์ถฉ๋Œ์ด ์ผ์–ด๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด์™€ ๋‹ฌ๋ฆฌ, ๋‘๋ฒˆ์งธ ์˜ˆ์‹œ๋Š” ๊ฐ™์€ ๊ณณ์„ ์ ‘๊ทผํ•˜๊ธฐ๋•Œ๋ฌธ์— ์ถฉ๋Œ์ด ์ผ์–ด๋‚ฉ๋‹ˆ๋‹ค.

Conflicting Access to self in Methods

๊ตฌ์กฐ์ฒด์˜ ๋ฎคํ…Œ์ดํŒ… ๋ฉ”์†Œ๋“œ๋Š” ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋œ ์‹œ๊ฐ„ ๋™์•ˆ self์— ๋Œ€ํ•ด ์“ฐ๊ธฐ ์ ‘๊ทผ์„ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

struct Player {
    var name: String
    var health: Int
    var energy: Int

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

mutatin methos ์ธ restoreHealth()๋Š” ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋œ ์ˆœ๊ฐ„๋ถ€ํ„ฐ ๋ฆฌํ„ด๋ ๋•Œ๊นŒ์ง€ self์— ๋Œ€ํ•ด ์“ฐ๊ธฐ ์ ‘๊ทผ์„ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ, ์ ‘๊ทผ์— ๋Œ€ํ•ด ์ค‘์ฒฉ์ด ๋˜๋Š” ์ฝ”๋“œ๊ฐ€ ์—†๋‹ค.

ํ•˜์ง€๋งŒ, ์•„๋ž˜์ฒ˜๋Ÿผ in-out ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋‹ค๋ฅธ Player์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๋Š”๋‹ค๋ฉด ์ ‘๊ทผ์˜ ์ค‘์ฒฉ์ด ์ƒ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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๊ฐ€ maria์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์— ์ถฉ๋Œ์ด ์ผ์–ด๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์œ„ ํ•จ์ˆ˜๋Š” oscar์— ๋Œ€ํ•ด ์“ฐ๊ธฐ ์ ‘๊ทผ์ด ์ผ์–ด๋‚˜๊ณ (mutating ๋ฉ”์†Œ๋“œ์ด๊ธฐ๋•Œ๋ฌธ์—) in-out ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์€ maria์— ๋Œ€ํ•ด์„œ๋„ ๋™์ผํ•œ ์‹œ๊ฐ„๋™์•ˆ ์“ฐ๊ธฐ ์ ‘๊ทผ์ด ์ผ์–ด๋‚œ๋‹ค. ํ•˜์ง€๋งŒ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋‹ค๋ฅธ ์ง€์—ญ์„ ์ ‘๊ทผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ถฉ๋Œ์ด ์ผ์–ด๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ oscar.shareHealth๊ฐ€ oscar๋ฅผ in-out parameter๋กœ ๋ฐ›๋Š”๋‹ค๋ฉด ์ถฉ๋Œ์ด ์ผ์–ด๋‚  ์ˆ˜ ์žˆ๋‹ค.

oscar.shareHealth(with: &oscar)
// Error: conflicting accesses to oscar

์œ„ ์ฝ”๋“œ์—์„œ๋Š” ๊ฐ™์€ ๊ณณ์„ ๊ฐ™์€ ์‹œ๊ฐ„์— ์ ‘๊ทผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ถฉ๋Œ์ด ์ผ์–ด๋‚  ์ˆ˜ ์žˆ๋‹ค.

Conflicting Access to Properties

๊ตฌ์กฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ๋‚˜ ํŠœํ”Œ์˜ element๋Š” ๊ฐ’ ํƒ€์ž…์ด๊ธฐ๋•Œ๋ฌธ, ๋ถ€๋ถ„์„ ์ˆ˜์ •ํ•ด๋„ ์ „์ฒด๊ฐ€ ๋‹ค ์ˆ˜์ •๋œ๋‹ค. ์ด ๋ง์€ ํ”„๋กœํผํ‹ฐ๋“ค ์ค‘ ํ•˜๋‚˜์— ๋Œ€ํ•œ ์ฝ๊ธฐ ์“ฐ๊ธฐ ์ ‘๊ทผ์€ ์ „์ฒด ํƒ€์ž…์— ๋Œ€ํ•œ ์ฝ๊ธฐ, ์“ฐ๊ธฐ ์ ‘๊ทผ์ด๋ผ๊ณ  ํ•œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋Š” ์ถฉ๋Œ์„ ์ผ์œผํ‚จ๋‹ค.

var playerInformation = (health: 10, energy: 20)
balance(&playerInformation.health, &playerInformation.energy)
// Error: conflicting access to properties of playerInformation

์œ„์˜ ์ผ€์ด์Šค์—์„œ balance()์— in-out ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ playInformation์˜ health์™€ energy๊ฐ€ ๋„˜์–ด์˜ค๋Š”๋ฐ ๊ฐ๊ฐ ์ „์ฒด ํƒ€์ž…์— ์“ฐ๊ธฐ ์ ‘๊ทผ์ด ์ผ์–ด๋‚œ๋‹ค. health์— ์˜ํ•ด์„œ ์ ‘๊ทผ๋œ ๋ฉ”๋ชจ๋ฆฌ์™€ energy์— ์˜ํ•ด ์ ‘๊ทผ๋œ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๊ฐ™์€๊ณณ์ด๊ณ , ๊ฐ™์€ ์‹œ๊ฐ„์ด๊ธฐ ๋•Œ๋ฌธ์— ์ถฉ๋Œ์„ ์ผ์œผํ‚จ๋‹ค.

์œ„์™€ ๋น„์Šทํ•œ ์˜ˆ๊ฐ€ ์ „์—ญ๋ณ€์ˆ˜๋กœ ์„ ์–ธ๋œ ๊ตฌ์กฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ ์ ‘๊ทผ์—์„œ๋„ ์ผ์–ด๋‚ฉ๋‹ˆ๋‹ค.

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
}

์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์œ„์™€ ๊ฐ™์€ ์ƒํ™ฉ์€ ๋ฉ”๋ชจ๋ฆฌ ์„ธ์ดํ”„ํ‹ฐํ•˜๋‹ค๊ณ  ๋ณด์žฅํ•ด์ฃผ๊ฒŒ ๋œ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๋‘๊ฐœ์˜ ์ €์žฅํ”„๋กœํผํ‹ฐ๊ฐ€ ์–ด๋–ค์‹์œผ๋กœ๋“  ์„œ๋กœ ์—ฐ๊ด€์ด ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๊ตฌ์กฐ์ฒด์— ํ”„๋กœํผํ‹ฐ์— ๋Œ€ํ•œ ์ค‘์ฒฉ ์ ‘๊ทผ์„ ์ œํ•œํ•œ๋‹ค๊ณ  ํ•ด์„œ ํ•ญ์ƒ ๋ฉ”๋ชจ๋ฆฌ ์„ธ์ดํ”„ํ‹ฐํ•œ ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ์„ธ์ดํ”„ํ‹ฐ ์ด์ƒ์œผ๋กœ ํ•ด๋‹น ๋ฉ”๋ชจ๋ฆฌ์— ๋Œ€ํ•œ ์ ‘๊ทผ์ด ๋ฐฐํƒ€์ ์ด์–ด์•ผ ํ•œ๋‹ค. ์ด ๋ง์€ ์–ด๋– ํ•œ ์ ‘๊ทผ์ด ๋ฉ”๋ชจ๋ฆฌ ์„ธ์ดํ”„ํ‹ฐ ํ•˜์ง€๋งŒ ๋ฉ”๋ชจ๋ฆฌ์— ๋ฐฐํƒ€์ ์œผ๋กœ ์ ‘๊ทผํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๋ง์ด๋‹ค. ์Šค์œ„ํ”„ํŠธ๋Š” ์œ„์™€ ๊ฐ™์€ ๋ฐฐํƒ€์ ์ด์ง€ ์•Š์€ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ์„ ๋ฉ”๋ชจ๋ฆฌ ์„ธ์ดํ”„ํ‹ฐํ•˜๋‹ค๊ณ  ๋ณด์žฅํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค. ์Šค์œ„ํ”„ํŠธ๊ฐ€ ๊ตฌ์กฐ์ฒด ํ”„๋กœํผํ‹ฐ์— ๋Œ€ํ•œ ์ค‘์ฒฉ ์ ‘๊ทผ์„ ๋ฉ”๋ชจ๋ฆฌ ์„ธ์ดํ”„ํ•œ๊ฒƒ์œผ๋กœ ํŒ์ •ํ•ด ์ฃผ๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์กฐ๊ฑด์ด ํ•„์š”ํ•˜๋‹ค.

  • ์˜ค์ง ์ธ์Šคํ„ด์Šค์˜ ์ €์žฅ ํ”„๋กœํผํ‹ฐ์—๋งŒ ์ ‘๊ทผํ•ด์•ผ ํ•œ๋‹ค. ๊ณ„์‚ฐ ํ”„๋กœํผํ‹ฐ๋‚˜ ํด๋ž˜์Šค ํ”„๋กœํผํ‹ฐ๋Š” ์•ˆ๋œ๋‹ค.

  • ๊ตฌ์กฐ์ฒด๋Š” ๋กœ์ปฌ ๋ณ€์ˆ˜๋กœ ์„ ์–ธ๋˜์–ด์•ผ ํ•œ๋‹ค. ์ „์—ญ ๋ณ€์ˆ˜๋กœ ์„ ์–ธ๋˜๋ฉด ์•ˆ๋œ๋‹ค.

  • ๊ตฌ์กฐ์ฒด๋Š” ํด๋กœ์ €์— ์˜ํ•ด ์บก์ฒ˜๋˜๊ฑฐ๋‚˜ ์บก์ฒ˜๋˜๋”๋ผ๋„ nonescaping ํด๋กœ์ €์— ์˜ํ•ด์„œ ์บก์ฒ˜๋˜์–ด์•ผ ํ•œ๋‹ค.

๋งŒ์•ฝ ์œ„์™€ ๊ฐ™์€ ์กฐ๊ฑด์ด ์„ฑ๋ฆฝ๋˜์ง€ ์•Š์œผ๋ฉด ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•˜์ง€ ๋ชปํ•œ๋‹ค.