Memory 관리

seocho·2022년 8월 25일
0

iOS

목록 보기
6/24

이미지 캐쉬

  • 메모리가 일정 값을 초과했을 때 큐마냥 선입 선출

즉각 접근 vs 장기 접근

즉각 접근

: 코드에서 메모리 접근이 시작되고 끝나기 전에 그 메모리에 대한 다른 접근이 시작될 수 없을 때를 의미

장기 접근

: 장기 접근은 시작되고 종료되기 전에 다른 코드가 실행될 수 있음 → 오버랩 overlap

다양한 상황

In-Out 파라미터에 충돌 접근

  • 함수는 모든 in-out 파라미터에 장기 쓰기 접근을 가지고 있음
  • in-out 파라미터에 대한 쓰기 접근은 모든 non in-out 파라미터가 평가된 후에 시작되고 해당 함수 호출동안 지속됨.
  • in-out 파라미터가 여러 개인 경우 쓰기 접근은 파라미터가 나타나는 순서와 동일하게 시작됨
func increment(_ number: inout Int) {
    number += stepSize
}

increment(&stepSize)
// Error: conflicting accesses to stepSize

해결 방법

  • 복사본 지정
var copyOfStepSize = stepSize
increment(&copyOfStepSize)

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

메소드에서 self에 충돌 접근

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

    static let maxHealth = 10
    mutating func restoreHealth() {
        health = Player.maxHealth 
				// self에 쓰기 접근은 메소드 반환될 때까지 유지
    }
}

extension Player {
		// shareHealth(with:) 메소드는 in-out 파라미터로 다른 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. 중복 야기 X
// oscar는 변경 함수에서 self의 값이기 때문에 oscar에 대한 쓰기 접근
// maria는 in-out 파라미터로 전달되기 때문에 maria에 대한 쓰기 접근

// 그러나 shareHealth(with:) 의 인자로 oscar를 전달하면 충돌 발생
oscar.shareHealth(with: &oscar)
// Error: conflicting accesses to oscar
// 변경 메소드는 self에 대한 쓰기 접근이 필요, in-out 파라미터는 teammate에 쓰기 접근 필요
// 메소드 내에서 self와 teammate는 메모리의 같은 위치를 참조, 쓰기 접근 오버랩되므로 충돌

프로퍼티에서 충돌 접근

var playerInformation = (health: 10, energy: 20)
balance(&playerInformation.health, &playerInformation.energy)
// Error: conflicting access to properties of playerInformation
// playerInformation에 중복 쓰기 접근이므로 충돌
// playerInformation.health, playerInformation.energy는 쓰기 접근이 필요한 in-out 파라미터

// 전역 변수에 저장된 구조체의 프로퍼티에 쓰기 접근 중복될 때 에러
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
}
// 위에서 oscar의 health, energy는 2개의 in-out 파라미터로 전달
// 2개의 저장된 프로퍼티는 상호작용하지 않으므로 안전

구조체의 프로퍼티에 중복 접근이 안전하다고 증명할 수 있는 경우

  • 계산된 프로퍼티 또는 클래스 프로퍼티가 아닌 인스턴스의 저장된 프로퍼티만 접근
  • 구조체는 전역 변수가 아닌 지역 변수의 값임
  • 구조체는 클로저에 의해 캡쳐되지 않거나 nonescaping 클로저에 의해서만 캡쳐됨

참고

메모리 안전성 (Memory Safety)

profile
iOS 개린이

0개의 댓글