관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - Xcode] Memory Leak, strong Reference, cycle 확인 방법 (with Instruments) 본문

Git, CocoaPods, Xcode, Shell

[iOS - Xcode] Memory Leak, strong Reference, cycle 확인 방법 (with Instruments)

jake-kim 2021. 7. 10. 22:03

Memory Leak

  • 메모리 누수는 인스턴스가 할당되었지만, 앱에서 더 이상 사용하지 않음에도 불구하고 해제되지 않은 메모리
  • 블록이나 세션에 대한 참조가 없으면 해제할 방법이 없는 경우 존재

Instrumnets 도구

  • Xcode에 통합된 일련의 애플리케이션 성능 분석 도구
  • Allocation 상태를 확인 가능
  • Memory leak 상태 확인 가능

Instrument 사용하여 Memory Leak 분석

  • Instruments의 
  • cmd + I로 'Profile' 실행 (I는 Instruments를 의미)
    • 또는, Xcode > Run 아이콘 부분을 long 클릭 > Profile 선택 > Instruments 앱 자동 실행 > Leaks 선택
    • 주의: "permission denied"오류 메시지 뜨는 경우, provisioning profile이 distribution일때 뜨므로 build sceme에서 apple development로 설정 필요

영상에서는 Allocation을 선택하지만, 'Leak'을 선택

  • '녹화' 버튼을 탭하면 앱이 실행되면서 수치 기록

Memory leak 확인 방법

// reference cycle 테스트를 위한 클래스 정의

class A {
    var b: B?
}

class B {
    var a: A?
}
// reference cycle로 인한 memory leak 설정

class VC2: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let a = A()
        let b = B()

        print("a count = \(CFGetRetainCount(a))") // 2
        print("b count = \(CFGetRetainCount(b))") // 2

        a.b = b
        b.a = a

        print("a count = \(CFGetRetainCount(a))") // 3
        print("b count = \(CFGetRetainCount(b))") // 3

    }
}
  • Instruments > Leaks 선택 후, VC2화면 진입 시 reference count와 leak이 발생하는지 확인

  • Memory Leak확인 방법
    • 앱 이름 (MyTest) 검색창에 입력
    • 빨간색 X 표시 확인
    • MyTest.A와 MyTest.B는 두 번째 화면에서 사용된 프로퍼티인데, 두 번째 화면을 dismiss해도 남아있는 것 확인
    • persistent #의 갯수가 1이 아닌 2로 누적되는 상황 확인

  • Network 처리 중 closure에서 memory leak이 발생하는 경우
    • VC2화면으로 이동 시 객체들이 아직 사라있고 해제되지 않아서 VC2객체들이 쌓이는 형태
class VC2: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        delayedAllocAsyncCall()
    }

    func delayedAllocAsyncCall() {
        let url = URL(string: "https://www.google.com:81")!

        let sessionConfig = URLSessionConfiguration.default
        sessionConfig.timeoutIntervalForRequest = 999.0
        sessionConfig.timeoutIntervalForResource = 999.0
        let session = URLSession(configuration: sessionConfig)

        let task = session.downloadTask(with: url) { localURL, _, error in
            guard let localURL = localURL else { return }
            let contents = (try? String(contentsOf: localURL)) ?? "No contents"
            print(contents)
            print(self.view.description) // Strong Capture를 통해 VC2 메모리 Leak 발생
        }
        task.resume()
    }
}

 MyTest.VC2가 해제되지 않고 쌓이는 현상 확인

 

Comments