ARC

hyun·2025년 6월 17일
0

iOS

목록 보기
18/54

 Automatic Reference Counting (ARC)

Swift && Objective-C에서 사용하는 메모리 관리 기법
객체에 대한 참조 카운트를 추적해서 사용되지 않는 메모리를 해제하는 메커니즘
직접 메모리 해제를 관리하지 않아도 돼서 메모리 관리 부담 감소

객체가 생성될 때 참조 카운트가 1로 시작되고 다른 객체나 변수에서 해당 객체를 참조할 때 참조 카운트가 증가

참조가 해제되거나 범위를 벗어나면 참조 카운트가 감소

참조 카운트가 0이 되는 시점에 ARC가 자동으로 메모리를 해제

→ 객체가 사용 중인지 아닌지 참조 수를 기반으로 판단해서 메모리를 자동으로 반환

 ARC 동작 원리 && 내부 처리

컴파일러는 소스코드 파싱 후 Intermediate Representation인 SIL 생성 과정에서 ARC 관련 명령어를 넣음

retain : 참조 카운트 1 증가

release : 참조 카운트 1 감소

ex)
객체가 생성되는 시점에는 retain 명령어가 삽입돼서 참조 카운트 증가
객체에 대한 참조가 해제되거나 변수 스코프가 끝나면 release 명령어가 삽입돼서 카운트가 감소

SIL 명령어 레벨에서 ARC 코드가 자동 생성

%1 = function_ref @$s...ObjectACACycfC : ...    // ObjectA() 생성, RC +1

ARC는 컴파일러가 자동으로 참조 관리 코드를 생성, 직접 메모리 할당/해제를 신경쓰지 않아도 됨

 ARC 한계 && 메모리 누수

참조 카운트 증가/감소만 자동 관리하고, 참조 간의 순환 구조를 탐지하거나 해제하는 건 못함

순환 참조

두 객체가 강한 참조로 갖고 있을 때, 참조 카운트가 0으로 감소하지 않아 메모리 해제가 불가능해짐

ex) 클래스 인스턴스 간의 강한 참조 || 클로저가 self를 강한 참조로 캡처하는 경우

메모리 누수를 완전히 막지는 못해서 참조 타입 관리가 중요

참조 타입: Strong, Weak, Unowned

참조 카운트 증가 여부를 결정하는 참조 타입

참조 타입참조 카운트 증감옵셔널 여부해제된 메모리 접근 시 행동
Strong+1 (카운트 증가)아님메모리 해제 방지
Weak카운트 증가 안함옵셔널(Optional) 타입해제되면 nil로 자동 설정, 안전한 접근 가능
Unowned카운트 증가 안함옵셔널 아님해제된 객체 접근 시 런타임 크래시 발생

Strong Reference : 기본 참조 타입. 객체의 생명주기 연장

Weak Reference : 메모리 누수 방지를 위해 참조 카운트를 증가시키지 않고
객체가 해제되면 자동으로 nil로 바뀜 (안정성 보장!), 옵셔널 타입

Unowned Reference : 참조 카운트를 증가시키지 않지만 옵셔널이 아니고
객체가 해제된 뒤에 접근하면 런타임 에러가 발생함 weak보다 빠르지만 안전성이 떨어짐

 ARC && SideTable

객체의 참조 카운트는 객체 내부에 저장되지만 Weak 참조를 위한 추가 메타데이터는 SideTable에 관리됨

 Autorelease Pool

클래스는 기본적으로 즉시 해제 방식으로 ARC 수행

Objective-C 런타임 객체, autorelease 메시지가 호출되면 Autorelease Pool에 등록돼서 release가 지연됨

Autorelease Pool이 해제될 때까지 객체의 참조 카운트 감소를 미뤄두었다가 일괄 처리

 메모리 누수 && 감지 방법

누수 원인

순환 참조로 인해 참조 카운트가 0이 되지 않는 경우

Closure가 self 또는 다른 객체를 강한 참조로 캡처하는 경우

ARC 관리 밖 객체를 생성/사용 후 해제하지 않는 경우

감지 방법

Xcode Instruments의 Leak Instrument로 실행 중 누수 탐지

Memory Graph Debugger로 앱 실행 시점 객체 참조 관계 시각화

클래스 deinit에 로그를 추가해 예상대로 메모리가 해제되는지 확인

0개의 댓글