Objective-C에서 자동 참조 카운트는 어떤 종류의 누출을 방지하거나 최소화하지 않습니까?


235

Mac 및 iOS 플랫폼에서 메모리 누수는 종종 해제되지 않은 포인터로 인해 발생합니다. 전통적으로 할당, 복사 및 보유를 확인하여 각각에 해당 릴리스 메시지가 있는지 확인하는 것이 항상 가장 중요했습니다.

Xcode 4.2와 함께 제공되는 툴체인은 최신 버전의 LLVM 컴파일러 와 함께 ARC (Automatic Reference Counting)를 도입했습니다 . 그것은 매우 시원하며 불필요한 불필요한 평범한 개발 시간을 줄이고 적절한 유지 / 릴리스 균형으로 수정하기 쉬운 부주의 한 메모리 누수를 방지합니다. Mac 및 iOS 앱에 대해 ARC를 활성화하면 자동 릴리스 풀도 다르게 관리해야합니다 ( NSAutoreleasePool더 이상 자체 할당하지 않아야 함 ).

그러나 다른 는 메모리 누수를 않습니다 하지 난 아직도 조심해야한다는 방지?

보너스로 Mac OS X 및 iOS의 ARC와 Mac OS X의 가비지 수집의 차이점은 무엇입니까?

답변:


262

여전히 기억해야 할 주요 메모리 관련 문제는 유지주기입니다. 한 객체가 다른 객체에 대한 강한 포인터를 가지고 있지만 대상 객체에 원래 포인터를 다시 가리키는 강력한 포인터가있을 때 발생합니다. 이러한 객체에 대한 다른 모든 참조가 제거 되더라도 여전히 서로 붙잡고 해제되지 않습니다. 체인의 마지막 체인이 이전 오브젝트를 다시 참조 할 수있는 오브젝트 체인에 의해 간접적으로 발생할 수도 있습니다.

이러한 이유로 __unsafe_unretained__weak소유권 한정자가 존재합니다. 전자는 객체가 가리키는 객체를 유지하지 않지만 객체가 사라질 가능성을 열어두고 메모리가 나쁜 메모리를 가리키는 반면 후자는 객체를 유지하지 않고 대상이 할당 해제되면 자동으로 nil로 설정됩니다. 둘 중 __weak일반적으로이를 지원하는 플랫폼에서 선호됩니다.

이 한정자를 사용하여 객체가 델리게이트를 유지하지 않고 사이클을 유발하지 않도록하는 델리게이트와 같은 항목에 사용할 수 있습니다.

또 다른 중요한 메모리 관련 문제는 Core Foundation 객체 malloc()및와 같은 유형에 사용하여 할당 된 메모리를 처리하는 것 char*입니다. ARC는 이러한 유형을 관리하지 않으며 Objective-C 객체 만 관리하므로 여전히 직접 처리해야합니다. 핵심 Foundation 유형은 때로는 까다로울 수 있습니다. 때로는 일치하는 Objective-C 객체에 브리지되어야하고 그 반대도 마찬가지입니다. 이는 CF 유형과 Objective-C를 브리징 할 때 ARC에서 제어를 앞뒤로 전송해야 함을 의미합니다. 이 브리징과 관련된 일부 키워드가 추가되었으며 Mike Ash는 그의 긴 ARC 글 에서 다양한 브리징 사례에 대해 잘 설명 했습니다 .

이 외에도, 게시 된 사양 이 자세하게 설명 되는 몇 가지 덜 빈번하지만 여전히 문제가되는 경우가 있습니다 .

객체에 대한 강력한 포인터가있는 한 객체를 유지하는 것을 기반으로하는 많은 새로운 동작은 Mac의 가비지 수집과 매우 유사합니다. 그러나 기술적 토대는 매우 다릅니다. 이 스타일의 메모리 관리는 더 이상 지적되지 않는 객체를 정리하기 위해 정기적으로 실행되는 가비지 수집기 프로세스가 아니라 Objective-C에서 모두 준수해야하는 엄격한 유지 / 해제 규칙에 의존합니다.

ARC는 단순히 반복적 인 메모리 관리 작업을 몇 년 동안 수행하여 컴파일러로 오프로드하므로 다시 걱정할 필요가 없습니다. 이렇게하면 가비지 수집 플랫폼에서 경험할 수있는 정지 문제 나 톱니 메모리 프로파일이 없습니다. 가비지 수집 된 Mac 응용 프로그램에서이 두 가지를 모두 경험했으며 ARC에서 어떻게 작동하는지 알고 싶어합니다.

가비지 수집 대 ARC에 대한 자세한 내용 은 Objective-C 메일 링리스트 에서 Chris Lattner의 매우 흥미로운 응답을 참조하십시오 . 여기서 Objective-C 2.0 가비지 수집에 비해 ARC의 많은 장점을 나열합니다. 나는 그가 설명하는 몇 가지 GC 문제에 부딪쳤다.


2
자세한 답변 주셔서 감사합니다. 나는 _unsafe_unretained 아래에 델리게이트를 정의하고 응용 프로그램이 중단 된 후에 같은 문제가 발생했습니다. 나중에 강하게 변경하여 수정했지만 이제는 메모리 누수가 발생합니다. 그래서 나는 그것을 약하게 바꾸었고 매력처럼 작동합니다.
chathuram

@ichathura 와우! 당신은 나를 ARC 열광에서 구했습니다. CMPopTipView를 사용할 때 동일한 충돌이 발생했습니다.
Nianliang 2016 년

@BradLarson : "가비지 수집 플랫폼에서 경험 한 정지 문제 나 톱니 메모리 프로파일이 없습니다." 스코프 기반 교정에서 더 나쁜 정지 및 톱니 메모리 프로파일과 참조 횟수 계산에서 훨씬 더 나쁜 성능을 기대하므로 실제 비교를 원합니다.
Jon Harrop

브래드, 크리스 래트너의 연결이 끊어 졌습니다 . 100 %는 아니지만이 다른 링크를 찾았습니다. 내가 생각하기에 당신이 링크하고자하는 것 : lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160208/…
Honey

1
@Honey-지적 해 주셔서 감사합니다. 연결 한 링크가 약간 다르지만 사용 불능 링크를 보관 된 원본 메시지 버전으로 교체했습니다. 메일 링리스트 보관소에 있으며 어딘가에서 구할 수 있지만 새 위치를 찾을 수 있는지 살펴 보겠습니다.
Brad Larson

14

ARC는 비 OBJC 메모리를 사용하는 데 도움이되지 않습니다. 예를 들어 malloc()무언가 필요한 경우 여전히 메모리 가 필요 free()합니다.

performSelector:컴파일러가 선택기가 무엇인지 알아낼 수 없으면 ARC가 속일 수 있습니다 (컴파일러는 경고를 생성합니다).

ARC는 또한 ObjC 명명 규칙에 따라 코드를 생성하므로 ARC와 MRC 코드를 혼합하면 MRC 코드가 컴파일러가 이름에서 약속 한대로 작동하지 않으면 놀라운 결과를 얻을 수 있습니다.


7

다음 4 가지 문제로 인해 애플리케이션에서 메모리 누수가 발생했습니다.

  1. 뷰 컨트롤러를 닫을 때 NSTimers를 무효화하지 않음
  2. 뷰 컨트롤러를 닫을 때 NSNotificationCenter에 대한 관찰자를 제거하는 것을 잊었습니다.
  3. 블록에서 자기에 대한 강한 언급을 유지합니다.
  4. 뷰 컨트롤러 속성에서 델리게이트에 강력한 참조 사용

운 좋게 나는 다음 블로그 게시물을 보았고 수정할 수있었습니다 .


0

ARC는 CoreFoundation 유형도 관리하지 않습니다. CFBridgingRelease()Objective-C / Cocoa 객체로 사용하려는 경우에만 '브리지'할 수 있습니다 (사용 ). CFBridgingRelease는 CoreFoundation 유지 횟수를 1 씩 줄이고 Objective-C의 ARC로 옮깁니다.


0

Xcode 9는 이러한 종류의 문제를 찾기위한 훌륭한 도구를 제공합니다. " 디버그 메모리 그래프 "라고합니다. 그것을 사용하면 클래스 유형별로 누출 된 객체를 찾을 수 있으며 거기에서 릴리스하여 문제를 해결함으로써 누가 강한 참조를 보유하고 있는지 알 수 있습니다. 또한 메모리주기를 감지합니다.

그것을 사용하는 방법에 대한 자세한 정보를 참조하십시오

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.