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