Danny의 iOS 컨닝페이퍼
article thumbnail

메모리 누수(Memory Leak) 란?

프로그램에서 사용한 메모리를 해제하지 않고 계속 사용하는 상황을 의미합니다. 

두 객체 이상이 서로를 참조할 때 참조가 끊기지 않는 문제점(Retain Cycle)이 발생하게 되죠.

이런 상황은 시스템의 리소스가 부족해지거나 앱이 충돌하는 등의 문제를 발생시킵니다.

 

메모리 누수를 해결하려면 기본적으로 누수가 발생하는 객체를 해제해야 합니다.

객체를 참조하는 변수를 nil으로 설정하거나 weak, unowned와 같은 키워드를 통해 참조를 관리할 수 있죠.

 

 

디버깅 방법

확인 방법으로는 이와 같이 2가지 방법이 있습니다.

Debug Memory Graph 그리고 Profile에서 Leaks Instrument

사용방법에 대하여 알아봅시다.

 

일단 코드는 이와 같습니다.

SecondVC로 이동 시 서로를 순환 참조 시키도록 만들었습니다.

class AClass {
    var aProperty: BClass?
}

class BClass {
    var bProperty: AClass?
}

class SecondVC: UIViewController {
    
    var a = AClass()
    var b = BClass()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = .red
    
        // 서로를 참조하여 Retain Cycle을 발생 시켰습니다.    
        a.aProperty = b
        b.bProperty = a
    }
}

 

 

Debug Memory Graph 사용

기본적인 세팅을 해줘야 합니다.

 

Malloc Scribble?

동적 메모리 할당 시에 메모리를 더미 값(dummy value)으로 초기화하고, 이후에 해제되기 전까지 해당 메모리 공간에 쓰기 작업이 발생하는지 여부를 감지하는 기능입니다. 이를 통해 미리 선언하지 않은 포인터나 배열 범위를 벗어나는 등의 메모리 오버라이드를 찾아내어 디버깅을 보다 쉽게 할 수 있습니다.

 

Malloc Stack Logging?

동적 메모리 할당 및 해제 작업에 대한 스택 추적 정보를 수집하는 기능입니다. 이를 통해 메모리 할당 및 해제 작업이 어디서 발생하는지 파악하여 디버깅을 보다 쉽게 할 수 있습니다.

 

이런 처리를 해준다고 하네요. 체크를 해줍시다.

 

Debug Memory Gragh는 힙의 영역에 대한 메모리 스냅샷을 찍어서 보여주는 방식입니다.

앱 실행 후 Debug Memory Graph를 클릭해 주세요.

 

그러면 이와 같이

왼쪽 창에서는 현재 생성된 객체들이 나타나고

오른쪽 창에서는 그 객체들이 가리키는 참조(reference) 방향과 함께 연결된 객체들이 나타납니다.

 

오른쪽 창의 객체를 연결하는 화살표를 살펴보면

연한 화살표는 약한 참조를 나타냅니다.

굵은 화살표는 강한 참조를 나타냅니다.

 

 

이제 메모리 누수를 찾아봅시다.

 

첫 번째 방법으로는 계속 참조된 루트를 따라가면서 어디서 강한 참조로 연결되어 있는지 확인을 하는 것입니다.

 

아래 그림을 확인해 보면

BClass에서 AClass로 강한 참조로 연결돼 있고, 또 BClass로 강한 참조 연결이 계속됩니다.

이와 같이 루트를 따라가면서 누수를 찾는 방법이 있습니다.

 

다른 방법으로는 Debug Navigator에서 확인을 하는 것입니다.

정상적이라면 종료 시 메모리도 같이 사라지지만 순환참조가 일어나고 있을 경우 객체가 계속적으로 추가되죠.

 

예시를 위해 테스트를 위해 누수가 발생할 행동을 몇 번 반복해 줍시다.

 

현재 3번 반복을 했는데, 그만큼 객체가 증가한 걸 확인할 수 있습니다.

 

또한 현재 누수가 일어나는 객체를 한눈에 확인하려면

하단의 느낌표를 눌러 한눈에 모아볼 수도 있습니다.

 

이런 식으로 간편히 어떤 객체가 누수가 일어나고 있는지 확인이 가능한데

분명히 순환참조가 일어나고 있는데 표시가 안될 경우도 빈번합니다. 

 

이럴 땐 개발자가 직접 어디서 누수가 일어나는 찾아 확인을 해줘야 합니다.

 

마지막으로 사용 메모리 크기를 확인하는 방법이 있습니다.

 

객체의 사용이 종료되면 메모리가 사라져야 되는데

사라지지 않고 계속 증가한다면 어디선가 순환 참고가 일어나고 있다고 생각할 수 있습니다.

 

 

Leaks Instrument 사용

Leaks Instrumnets는 앱의 메모리 사용을 모니터링하고 관리는 도구입니다.

 

Product의 Profile로 접근합니다.

(단축키 command + i)

 

Instrument에서 Leaks으로 접근을 해줍니다.

그러면 사용준비 완료입니다!

 

각각의 역할에 대하여 간략 설명

 

이 도구는 실시간으로 어디서 누수가 일어나고 있는지 확인을 도와줍니다.

 

Allocations

앱에서 발생한 모든 메모리 할당과 해제 이벤트를 기록합니다.

 

Leaks

앱에서 메모리 누수를 감지하는 도구입니다.

객체 누수 및 참조를 식별하고 객체가 할당되거나 해제된 위치를 추적하여 누수의 원인을 파악합니다.

시작은 상단의 녹음 버튼을 통해 할 수 있고

하단의 필터를 통해 원하는 정보만을 얻을 수도 있습니다.

 

실행을 해봅시다.

이와 같이 해제가 되지 않고 계속 쌓이고 있습니다.

 

또한, Cycles & Roots에서 어떻게 순환참조가 일어나고 있는지 그래프를 통해 친절하게 알려줍니다.

 

 

이렇게 오늘은 메모리 누수 디버깅방법에 대하여 알아보았습니다.

부족한 설명이지만, 조금은 이해 가셨나요?

틀린 내용이 있다면 언제든지 지적해 주시면 감사히 받겠습니다. 🫠
읽어주셔서 감사합니다 😃

 

 

참고

https://ios-development.tistory.com/604

반응형
profile

Danny의 iOS 컨닝페이퍼

@Danny's iOS

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!