디버깅을 통해 메모리 누수 찾기
메모리 누수 (Memory Leak)
•
프로그램에서 사용한 메모리를 해제하지 않고, 계속 사용하는 상황을 의미
•
두 객체 이상이 서로를 참조할 때, 참조가 끊기지 않는 문제점(Retain Cycle)이 발생
•
이런 상황은 시스템의 리소스가 부족해지거나 앱이 충돌하는 등의 문제를 발생시킨다.
메모리 누수를 해결하려면 기본적으로 누수가 발행하는 객체를 해제해야 한다.
객체를 참조하는 변수를 nil로 설정하거나 weak, unowned 와 같은 키워드를 통해 참조를 관리할 수 있다.
디버깅 방법
•
Debug Memory Graph
•
Profile → Leaks Instrument
예제코드
//
// ViewController.swift
// MemoryLeaksTest
//
// Created by Hyungjun KIM on 9/4/24.
//
import UIKit
class AClass {
var aProperty: BClass?
}
class BClass {
var bProperty: AClass?
}
class ViewController: UIViewController {
var a = AClass()
var b = BClass()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .blue
// 서로를 참조하여 Retain Cycle을 발생
a.aProperty = b
b.bProperty = a
}
}
Swift
복사
ViewController로 이동 시 서로를 순환참조 시키도록 만들었다.
Debug Memory Graph 사용
Malloc Scibble
•
동적 메모리 할당 시에 메모리를 더미 값(dummy value)으로 초기화하고, 이후에 해제되기 전까지 해당 메모리 공간에 쓰기 작업이 발생하는지 여부를 감지하는 기능
•
이를 통해, 미리 선언하지 않은 포인터나 배열 범위를 벗어나는 등의 메모리 오버라이드를 찾아내어 디버깅을 보다 쉽게 할 수 있다.
Malloc Stack Logging
•
동적 메모리 할당 및 해제 작업에 대한 스택 추적 정보를 수집하는 기능
•
이를 통해, 메모리 할당 및 해제 작업이 어디서 발생하는지 파악하여 디버깅을 보다 쉽게 할 수 있다.
•
Debug Memory Graph는 힙의 영역에 대한 메모리 스냅샷을 찍어서 보여주는 방식이다.
이와 같이 왼쪽 창에서는 현재 생성된 객체들이 나타나고
오른쪽 창에서는 그 객체들이 가리키는 참조(reference) 방향과 함께 연결된 객체들이 나타난다.
여기서 굵은 화살표가 강한 참조를 나타낸다.
메모리 누수 찾기
첫번째 방법
•
계속 참조된 루트를 따라가면서 어디서 강한 참조로 연결되어 있는지 확인하는 것
아래 그림을 확인해보면, BClass에서 AClass로 강한 참조로 연결되어 있고, 또 BClass로 강한 참조 연결이 계속 된다.
이와 같이 루트를 따라가면서 누수를 찾는 방법이 있다.
두번째 방법
•
Debug Navigator에서 확인하는 것
정상적이라면 종료 시 메모리도 같이 사라지지만 순환참조가 일어나고 있을 경우, 객체가 계속적으로 추가된다.
예시를 위해 테스트를 위해 누수가 발생할 행동을 몇 번 반복해준다.
한번 화면 이동
하단 느낌표를 누르면 누수가 일어나는 객체를 한눈에 볼 수 있다.
4번 화면 이동
이런 식으로 간편히 어떤 객체가 누수가 일어나고 있는지 확인이 가능한데,
분명히 순환참조가 일어나고 있는데 표시가 안될 경우도 빈번하다.
이럴땐, 직접 어디서 누수가 일어나는지 찾아 확인을 해야한다.
세번째 방법
•
사용 메모리 크기를 확인하는 방법
객체의 사용이 종료되면 메모리가 사라져야 되는데, 사라지지 않고 계속 증가한다면 어디선가 순환참조가 일어나고 있다고 생각할 수 있다.
Leaks Instrument 사용
Leaks Instruments는 앱의 메모리 사용을 모니터링하고 관리하는 도구이다.
Product → Profile (Command + i)
이 도구는 실시간으로 어디서 누수가 일어나고 있는지 확인을 도와준다.
•
Allocations
◦
앱에서 발생한 모든 메모리 할당과 해제 이벤트를 기록한다.
•
Leaks
◦
앱에서 메모리 누수를 감지하는 도구
◦
객체 누수 및 참조를 식별하고 객체가 할당되거나 해제된 위치를 추적하여 누수의 원인을 파악한다.
시작은 상단의 녹음 버튼을 통해 할 수 있고,
하단의 필터를 통해 원하는 정보만을 얻을 수도 있다.
이와 같이 해제가 되지 않고 계속 쌓이고 있다.
또한, Cycles & Roots에서 어떻게 순환참조가 일어나고 있는지 그래프를 통해 알 수 있다.