Jaebi의 Binary는 호남선

ARC (Automatic Reference Counting) 본문

Swift

ARC (Automatic Reference Counting)

jaebijae 2024. 7. 20. 04:34

ARC

  • 메모리 영역중 Heap 영역을 관리
    • Swift는 인스턴스, 클로저 등등 참조 타입을 자동으로 Heap에 할당
  • ARC는 클래스 인스턴스가 더 이상 필요하지 않을 때 메모리를 자동으로 해제함
  • Reference Count로 메모리를 관리 → 메모리 참조 횟수를 계산하여 참조 횟수가 0이 되면 더 이상 사용하지 않는 메모리라 판단하여 해제
  • 모든 인스턴스는 자신의 RC값을 가지고 있으며 누가 가르키고 있느냐 없느냐를 숫자로 표현됨

Process

class Human {
    var name: String?
    var age: Int?
    
    init(name: String?, age: Int?) {
        self.name = name
        self.age = age
    }
}
 
let sodeul = Human(name: "Sodeul", age: 26)
  • 지역 변수 jaebi는 Stack에 할당, Human 인스턴스는 Heap에 할당
  • sodeul은 일단 어디 클래스에 생성된 지역 변수라고 가정
  • 인스턴스를 새로 생성할 때 해당 인스턴스에 대한 RC 증가

let clone = sodeul
  • 인스턴스가 복사되지 않음으로 실제 메모리는 같은 Heap 영역의 인스턴스를 point
  • 기존 인스턴스를 다른 변수에 대입할 때도 RC 값 증가

func makeClone(_ origin: Human) {
    let clone = origin                       // ② Instance RC : 2
}
let sodeul = Human(name: "Sodeul", age: 26)  // ① Instance RC : 1
makeClone(sodeul)
                                             // ③ Instance RC : 1
  • 참조 횟수 내려가는 경우 # 1
    • sodeul이 생성되는 순간 인스턴스의 RC +1
    • makeClone의 sodeul을 참조하는 clone변수가 생성되면서 인스턴스의 RC +1
    • 인스턴스를 가르키던 변수가 메모리에서 해제되면서 RC -1

var sodeul: Human? = .init(name: "Sodeul", age: 26)  // ① Instance RC : 1
var clone = sodeul                                   // ② Instance RC : 2
 
clone = nil                                          // ③ Instance RC : 1
sodeul = nil                                         // ④ Instance RC : 0 (메모리 해제)
  • makeClone함수가 종료되어 메모리에서 해제됨
  • 또는 clone = nil 로 메모리에서 해제
  • 참조 횟수 내려가는 경우 # 2
    • nil이 지정 되면서 RC -1

var sodeul: Human? = .init(name: "Sodeul", age: 26)  // ① Sodeul Instance RC : 1
var clone: Human? = .init(name: "Sodeul2", age: 26)  // ② Clone Instance RC  : 1
 
sodeul = clone                                       // ③ Clone Instance RC  : 2, Sodeul Instance RC : 0 (메모리 해제)
  • 2개의 인스턴스 - sodeul, clone 생성
  • sodeul = clone 로 값을 대입
  • 참조 횟수 내려가는 경우 # 3
    • 변수에 다른 값을 대입
    • sodeul의 RC는 -1, clone의 RC는 +1
    • sodeul이 가르키던 인스턴스 RC가 0이 되면서 ARC가 자동으로 메모리 해제

class Contacts {
    var email: String?
    var address: String?
    
    init(email: String?, address: String?) {
        self.email = email
        self.address = address
    }
    deinit { print("Contacts Deinit)" } }
}

class Human {
    var name: String?
    var age: Int?
    var contacts: Contacts? = .init(email: "o_o@naver", address: "Suwon")
    
    init(name: String?, age: Int?) {
        self.name = name
        self.age = age
    }
    deinit { print("Human Deinit)" } }
}
 
let sodeul: Human? = .init(name: "Sodeul", age: 26)
sodeul = nil

  • Human 클래스 안에 contacts 클래스 인스턴스가 있음으로 두 인스턴스 각각의 RC 증가

  • sodeul에 nil을 할당한 순간 Human 인스턴스의 RC -1

  • Human의 RC가 0으로 되면서 메모리에서 해제 → contacts 프로퍼티도 메모리에서 해제 되면서 RC -1

  • Contacts 인스턴스도 RC가 0이 되며 메모리에서 해제
  • 참조 횟수 내려가는 경우 # 4
    • 프로퍼티의 경우 속해 있는 클래스 인스턴스가 메모리에서 해제
    • Human 클래스 안에 contacts 클래스 인스턴스가 있음으로 두 인스턴스 각각의 RC 증가
  • 유의사항:
    • Human 인스턴스가 메모리에서 해제 되면서 property인 contacts가 가르키던 Contacts인스턴스의 메모리도 같이 해제 되는게 아님 → RC가 -1 감소할 뿐
    • 따라서 RC가 0이 되었을때 인스턴스가 메모리에서 해제

Strong, Weak, Unowned

  Strong Weak Unowned
설명


  • 순환참조로 각각 RC +1이 되면서 cheolsu와 yeounghee를 nil로 대입시 메모리 해제가 되지 않고 heap에 남아 있음





  • 순환 참조이지만 weak로 선언되어 RC값을 올리지 않음

  • 인스턴스를 참조하는 도중에 인스턴스가 메모리에서 사라질 일이 없다고 확신 해야함

  • weak의 경우 cheolsu?.girlfriend -> nil
  • unowned의 경우 cheolsu?.girlfriend -> error: signal SIGABRT 발생
Reference Counting O X X
사용 시점
  • Default
  • 강한 순환 참조가 발생할 경우
  • 강한 순환 참조가 발생할 경우
  • 참조하는 인스턴스가 먼저 메모리에서 해제 될 가능성이 없을 시
특징
  • 강한 순환 참조(Circular Reference)로 인해 Memory leak 발생할 수 있음
  • 참조하던 인스턴스가 해제되면 자동으로 nil 할당
  • 수명이 더 짧은 인스턴스를 가르키는 애를 weak참조로 선언
  • 참조하는 인스턴스가 먼저 메모리에서 해제되면, 해제된 주소값을 게속 들고 있음 (에러 가능성)
  • unowned는 에러를 발생 시킬 위험이 있어 weak 권장
  • 수명이 긴 인스턴스를 가르키는 애를 unowned참조로 선언

Reference

 

iOS) 메모리 관리 (1/3) - ARC(Automatic Reference Counting)

안녕하세요~~ 소들입니다 👀 오늘은 지난 시간 메모리 구조에 이어 Swift를 사용할 때 메모리 관리가 어떤 식으로 되는지에 대해 공부해볼 거예요 :) ARC 면접 단골 질문이라죠? 깔깔 iOS 개발자라

babbab2.tistory.com

'Swift' 카테고리의 다른 글

App Lifecycle  (0) 2024.07.21
SwiftUI - App Protocol  (0) 2024.07.21
Swift - Memory 기초  (0) 2024.07.20
Swift - 문법 (접근 제어)  (0) 2024.07.20
Swift Local Network Connection  (0) 2024.06.19