Instruments에서 Leaks 감지가 안된다!

피터·2025년 10월 23일
post-thumbnail

안녕하세요. 오늘은 Instruments를 활용하는 법을 익히기 위해서
의도적으로 메모리 릭을 발생시키고 Instruments로 확인하는 과정을 해보았습니다.
그런데 Instruments에서 감지가 안 되는 문제가 발생했습니다.

Instruments를 잘 사용하는 개발자가 되고 싶은데 가장 허들이 높은 것 같습니다. 😭

테스트 코드

class ClassA {
    var x: ClassB?
}

class ClassB {
    var x: ClassA?
    deinit { print("메모리 해제") }
}

@objc func buttonTapped() {
    let classA = ClassA()
    let classB = ClassB()

    classA.x = classB  // 순환 참조 발생
    classB.x = classA
}

문제:

  • deinit이 호출되지 않음 (메모리 릭 확실)
  • Instruments에서 Leaks가 아예 감지 안 됨
  • Leaks를 감지해도 Stack Trace가 비어있음

해결 방법

1단계: Malloc Stack Logging 활성화

왜 감지가 안 되나?
iOS는 성능을 위해 메모리 할당 추적을 기본적으로 꺼놓는다고 합니다. 이게 꺼져있으면 Instruments가 어떤 메모리가 누수됐는지 알 수가 없습니다.

Malloc이란? C의 메모리 할당 함수. Swift에서 객체 생성 시 내부적으로 malloc()을 호출합니다.

설정 방법:
1. Product > Scheme > Edit Scheme (⌘<)
2. RunDiagnostics
3. ✅ Malloc Stack Logging 체크

결과: Leaks가 감지되기 시작했습니다! 하지만 Stack Trace는 여전히 비어있습니다.


2단계: DWARF with dSYM 설정

왜 Stack Trace가 비어있나?
컴파일된 바이너리는 메모리 주소만 가지고 있습니다. 함수 이름, 파일명, 줄 번호 같은 심볼 정보는 별도 파일(dSYM)에 저장됩니다.

0x1a2b3c4d8  ← 이게 뭔지 알 수 없음

설정 방법:
1. 프로젝트 선택 → Build Settings
2. 검색: Debug Information Format
3. Debug/Release 모두 DWARF with dSYM File로 설정

이게 하는 일:

메모리 주소 → dSYM 파일 → ViewController.swift:47

3단계: Recording 중지 후 확인

함정: Instruments는 Recording 중에는 실시간 감지만 하고, 중지 후에 상세 분석을 시작합니다.

Recording 중 (Stack Trace 비어있음)

Recording이 진행 중일 때는 Stack Trace가 비어있습니다.

Recording 중지 후 (Stack Trace 생성됨!)

중지를 하니 Stack Trace의 내용이 추가되었습니다!

올바른 절차:
1. Profile 실행 (⌘I)
2. Leaks 템플릿 선택
3. 앱에서 버튼 여러 번 클릭
4. ⏹️ Recording 중지 ← 이때 Stack Trace 생성!
5. Leaks 선택 → Call Tree/Stack Trace 확인


4단계: Call Tree 필터링으로 내 코드만 보기

Call Tree에서 내가 작성한 코드만 확인하고 싶다면, 시스템 라이브러리 호출을 필터링해야 합니다.

Call Tree 설정

아래 Call Tree 설정에서 다음을 선택:

  • Invert Call Tree - 호출 순서를 역순으로 (리프 노드부터 표시)
  • Hide System Libraries - 시스템 라이브러리 숨기기

결과: 관련된 내용만 남게 되어, 어디서 어떤 함수 호출로 메모리 릭이 생겼는지 명확하게 알 수 있습니다!


전체 흐름

메모리 릭 발생 → ❌ Leaks 감지 안 됨
                        ↓
        1. Malloc Stack Logging ON
                        ↓
          ✅ Leaks 감지! (Stack Trace 없음)
                        ↓
           2. DWARF with dSYM 설정
                        ↓
            3. Recording 중지
                        ↓
         ✅ Stack Trace 생성됨!
                        ↓
          4. Call Tree 필터링
                        ↓
      ✅ 내 코드만 깔끔하게 표시!

최종 결과

Stack Trace:
#0 swift_allocObject
#1 ClassA.__allocating_init() at ViewController.swift:10
#2 ViewController.buttonTapped() at ViewController.swift:47
#3 @objc ViewController.buttonTapped()

이제 정확히 ViewController.swift 47번째 줄에서 메모리 릭이 발생했음을 알 수 있습니다!


핵심 정리

Instruments로 메모리 릭 디버깅하려면 4가지 단계가 모두 필요합니다:

  1. Malloc Stack Logging - Leaks 감지 활성화
  2. DWARF with dSYM - 메모리 주소 → 소스 코드 변환
  3. Recording 중지 - 상세 분석 수행
  4. Call Tree 필터링 - 내 코드만 깔끔하게 표시

가장 많이 놓치는 것:

  • 1단계 Malloc Stack Logging을 켜지 않으면 Leaks가 아예 감지 안 됨
  • Recording을 중지하지 않으면 Stack Trace가 비어있음
profile
iOS 개발자입니다.

0개의 댓글