메모리 접근 안전

박형석·2021년 12월 13일
0

Swift

목록 보기
20/20
post-thumbnail

메모리 접근 충돌의 이해

프로그래머가 변수에 값을 할당한다던가, 함수의 전달인자로 변수의 값을 전달하는 등 다양한 경우에 코드를 통해 메모리에 접근하게 된다. 메모리 접근 충돌은 이 때 서로 다른 코드에서 동시에 같은 위치의 메모리에 접근할 때 발생한다.

메모리 접근의 특성

세 조건에 모두 해당하는 메모리 접근이 두 군데 이상의 코드에서 동시에 일어나면 메모리 접근 출동이 발생

  1. 최소한 한 곳에서 쓰기 접근
  2. 같은 메모리 위치에 접근
  3. 접근 타이밍이 겹침

접근 타이밍이 겹친다고 무조건 충돌이 발생하는 것은 아니지만 가능성이 크다.

  • 순차적 코드 실행, 순간적 메모리 접근, 단일 스레드 환경 → 충돌X
  • 하지만 단일 스레드라도 장기적 메모리 접근 방식 → 충돌 위험
  • inout Parameter / mutating function → 장기적 메모리 접근 방식을 사용

입출력 매개변수(inout Parameter)에서의 메모리 접근 충돌

  • inout 파라미터를 갖는 함수는 동작 중 장기적 메모리 접근한다.
    즉, inout 매개변수의 쓰기 접근이 시작되고 함수가 종료될 때까지 쓰기 접근을 유지한다.
    → 이 때 매개변수로 전달하는 변수는 다른 접근이 제한된다.
var step: Int = 1

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

increment(&step) // 런타임 오류! inout으로 전달되는 step은 접근 불가!
var step: Int = 1
var copyStep: Int = step

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

increment(&step) // 해결! 다른 값에 복사
  • 파라미터를 동시에 줘도 안된다.
func balance(_ x: inout Int, _ y: inout Int) {
 //...
}

var one = 42
var two = 45
balance(&one, &two) // 문제 없음
balance(&one, &one) // 오류!

메서드 내부에서 self 접근의 충돌

  • 구조체의 가변 메서드(mutating)는 실행 중에 self에 쓰기 접근
    → 인스턴스 자신인 self에 장기적 쓰기 접근
    → 따라서 다른 곳에서 self로 접근하거나 매개변수로 self를 받게 된다면 충돌

프로퍼티 접근 중 충돌

  • 구조체, 열거형 등은 프로퍼티로 구성, 튜플은 요소의 모임으로 구성
    이 프로퍼티나 요소는 각각 독립적인 값을 가진 타입의 구성요소, 이 세 가지는 값 타입
    → 자신의 인스턴스 내부의 프로퍼티를 변경한다는 것? 자신 스스로의 값을 변경한다는 것.
    → 프로퍼티에 읽고 쓰기 접근은 곧 자신 전체에 대한 읽고 쓰기 접근.
balance(&oscar.health, &oscar.energy)

두 매개변수는 inout parameter 그래서 함수가 실행 중이면, 두 매개변수 모두 쓰기 접근을 해야 한다. 쓰기 접근을 같은 위치에 동시에 하고 있기 때문에 충돌이 발생하게 된다.

  • 만약 실행될 코드 영역 외의 영역에서 접근할 가능성이 없다면 컴파일러는 오류로 취급하지 않는다. 아래는 지역 변수가 함수 내부에서만 접근 가능하고 이외의 가능성이 전혀없기 때문에 가능하다.
func somefunction() {
 var oscar = Player(name: "Oscar", health: 10, energy: 10)
 balance(&oscar.health, &oscar.energy)
}

어떻게 구조체 프로퍼티 메모리에 접근할 때 확실히 안전하다고 판단할 수 있을까?

  • 연산 프로퍼티나 클래스 프로퍼티가 아닌 인스턴스 저장 프로퍼티에만 접근
  • 전역 변수가 아닌 지역 변수일 때
  • 클로저에 의해 Capture되지 않았거나, 비탈출 클로저에 의해서만 획득되었을 때
profile
IOS Developer

0개의 댓글