[240103] Today I Learned

YoungHyun Kim·2024년 1월 3일
1

TIL ✍️

목록 보기
30/68

1. 메모리 구조

Code 영역

  • 프로그램의 실행 코드가 저장되는 공간, 컴파일된 소스 코드와 프로그램의 명령어들이 저장
  • 읽기 전용이며, 프로그램이 실행되면서 수정되지 않음

Data

  • 전역 변수와 정적 변수, 상수가 저장되는 곳
  • 프로그램 시작 시 할당되며, 프로그램 종료까지 유지됨

Heap

  • 프로그램 실행 중(런타임) 동적으로 할당된 데이터가 저장
  • 개발자가 직접 제어가 가능
  • 힙에 저장된 데이터는 포인터를 통해 접근가능
  • 메모리의 자유 공간을 사용하여 데이터를 저장하므로, 크기나 생존 기간에 대한 동적인 요구에 대응이 가능
  • 참조 타입이 저장되는 영역

Stack

  • 소스코드가 컴파일러에 의해 기계어로 변환되는 시점에 크기가 결정
  • 함수 호출과 관련된 정보를 저장하는 데 사용됨
  • 함수가 호출될 때마다 해당 함수의 로컬 변수, 함수 매개 변수, 반환 주소, 함수 호출에 필요한 기타 정보가 스택에 저장됨
  • 함수가 실행을 마치면 관련 데이터는 스택에서 제거됨
  • 값타입이 저장되는 영역

2. ⭐️⭐️ARC(Automatic Reference Counting)⭐️⭐️

Heap 영역의 객체에 대한 강한 참조 횟수를 추적하고, 객체가 더 이상 필요 없을 때 해당 메모리를 자동으로 해제하는 방식의 메모리 관리 방법

강한 참조(Strong Reference)

  • 변수나 상수는 기본적으로 강한 참조로 사용되며, 객체가 사용될 때마다 count가 1씩 증가됨
  • 해당 count가 증가되어 있다면, 그 객체는 메모리에 유지됨
class Person {
    var name: String
    init(name: String) {
        self.name = name
    }
}

var person1: Person? = Person(name: "Alice") // strong 참조
var person2 = person1 // 또 다른 strong 참조

// person1이 nil이 되더라도 person2가 여전히 strong 참조를 가지고 있으므로 객체는 메모리에 유지됨
person1 = nil

순환 참조(Circular References)

  • 두 객체가 서로를 강하게 참조하는 경우, 순환 참조가 발생
  • 두 객체 모두 더 이상 사용되지 않더라도, 두 객체가 서로를 강하게 참조하는 경우에 강한 참조 count가 감소하지 않아서 메모리에서 해제되지 않음 -> 메모리가 누수되는 문제가 발생!
class Person {
    var name: String
    var pet: Pet? // Person이 소유하는 Pet

    init(name: String) {
        self.name = name
    }
}

class Pet {
    var species: String
    var owner: Person? // Pet을 소유하는 Person

    init(species: String) {
        self.species = species
    }
}

var person: Person? = Person(name: "Alice") // Person 클래스의 인스턴스를 생성
var pet: Pet? = Pet(species: "Dog") // Pet 클래스의 인스턴스를 생성

person?.pet = pet // Person 클래스의 pet에 Pet 인스턴스를 할당
pet?.owner = person // Pet 클래스의 owner에 Person 인스턴스를 할당

약한 참조(Weak Reference)

  • weak 키워드를 사용한 약한 참조는 객체의 참조 count를 증가시키지 않기 때문에, 객체의 생명주기에 끼치는 영향없이 참조를 유지할 수 있다.
class Person {
    var name: String
    weak var friend: Person? // 약한 참조
    init(name: String) {
        self.name = name
    }
}

var person1: Person? = Person(name: "Alice")
var person2: Person? = Person(name: "Bob")
person1?.friend = person2
person2?.friend = person1

// person1이 메모리에서 해제됨, 그에 따라 person1과 연결된 모든 객체의 참조 카운트가 감소됨
person1 = nil

미소유 참조(Unowned Reference)

  • 약한 참조와 유사하지만, optional값이 아니기 때문에 nil이 될 수 없는 참조 방법
  • 참조하는 객체가 이미 메모리에서 해제된 상태에서 접근하려면 runtime error가 발생되며, 사용 시점에 객체가 이미 해제되지 않았다고 확신할 수 있는 경우에 사용해야 함!
class Country {
    var name: String
    var capital: City!
    init(name: String, capitalName: String) {
        self.name = name
        self.capital = City(name: capitalName, country: self)
    }
}

class City {
    var name: String
    unowned var country: Country // 미소유 참조
    init(name: String, country: Country) {
        self.name = name
        self.country = country
    }
}
profile
iOS 개발자가 되고 싶어요

0개의 댓글