iOS 메모리 할당/해제

GomHyeok·2024년 7월 8일

회고록

목록 보기
14/18

최근 받았던 한가지 질문이 있다.

iOS에서 메모리 할당/해제는 어떤 방식으로 관리하는가??

해당 질문에 명확하게 답변을 하지 못하여🥹 iOS 메모리 할당/해제 방식에 대하여 학습하였다.

📚 ARC

ARC = Automatic Reference Counting (그 전에는 MRC)
ios에서 메모리 관리를 단순화 + 효율화 하기 위해 도입된 기술이다.
개발자가 수동으로 메모리 할당 및 해제를 관리할 필요 없이 컴파일러가 자동으로 필요한 메모리 관리 코드를 추가한다
메모리 관리 측면에서 엄청난 장점을 가져다 주는 기능이다.

동작원리

  • 객체가 생성될 때 객체에 대한 참조 카운트가 증가한다.
  • 객체에 대한 참조가 해제되면 참조 카운트가 감소한다.
  • 참조 카운트가 0이 되면 ARC는 해당 객체의 메모리를 해제한다.

강한 참조와 약한 참조

최근 프로젝트를 진행하며 많이 사용했던 것이 weak(약한참조)이다. 강한 참조와 약한 참조는 참조 카운트에 영향을 주는 방식에서 차이를 가지고 있다. 해당 차이점은?

  • 강한 참조 : 객체에 대한 기본 참조 방식으로, 참조 카운트를 증가시킨다.
    -> 객체의 메모리가 해제되지 않도록 하기 위해 사용한다.
  • 약한참조 : 참조 카운트에 영향을 주지 않는 참조 방식
    -> 순환 참조 방지 + 참조 카운트가 0이 될 때 메모리에서 해제되어야 하는 객체를 참조할 때 사용

그리고 하나가 더 있다.

  • 미소유 참조/약한참조(unowned) : 해당 인스턴스의 소유권을 가지지 않으며 참조 카운트를 증가시키짖 않는다.
    -> nil이 될 수없다. optional로 선언 되어서는 안된다.

weak와 unowned의 차이

  • weak는 객체를 계속 추적하며 객체가 사라지면 nil로 바꾼다.
  • unowned는 객체가 사라지면 댕글링 포인터가 남는다 -> 참조시 crash 발생
    - 따라서 unowned는 사라지지 않을거라고 보장되는 객체에서 설정

댕글링 포인터(Dangling pointer) :
원래 바라보던 객체가 해제되면서 할당되지 않는 공간을 바라보는 포인터

📙 ARC의 해제 시점

위의 내용을 통해 참조 카운트가 0인 객체들이 결국 메모리에서 해제되어야 하는 객체임을 알 수 있었다. 이러한 메모리 관리는 메모리의 Heap영역에서 이루어진다. Heap영역은 참조타임의 데이터가 저당되고, 개발자가 동적메모리를 할당하는 공간이다.
하지만 정확한 해제 시점은 카운트가 0이되는 시점만 있는 것이 아니다.
그 전에 알아두면 좋은 것 -> retain, release함수(컴파일 시점에 자동으로 함수 넣어줌)

  • retain : RC 카운트 증가를 통해 현재 scope에서 객체의 유지를 보장
  • release : RC를 감소시킨다. 필요 없을 때 release함

여기서 필요 없을 때의 시점은 RC가 0이 되었을 때 deinit메서드를 통해 메모리가 해제된다.
하지만 Runloop iteration 동안 사용 중이거나 retain/release호출이 중첩되어있는 경우 다음 runloop iteration까지 해제가 지연될 수 있습니다.


📙 Autoreleasepool

  • 참조 카운트를 나중으로 미루기 위한, 나중에 감소되는 것을 보장받는 기법
  • release 대신 autorelease를 사용하면 예약이 된다.
  • autorelease된 객체들은 autoReleasePool에 등록된다 -> threadPool과 비슷한가..?

사용시 장점
autoReleasePool 블록 사용시 블록 종료되는 시점에서의 메모리 해제를 보장
-> 루프를 많이 돌아야 하는 경우 autoreleasepool을 명시적으로 선언하여 메모리를 최적화 할 수 있다.

profile
github : https://github.com/GomHyeok/

0개의 댓글