programing

코코아 및 목표-C를 사용한 참조 카운트 이해

lastmoon 2023. 6. 11. 11:12
반응형

코코아 및 목표-C를 사용한 참조 카운트 이해

이제 막 아이폰 SDK를 사용할 목적으로 오브젝티브-C와 코코아를 보기 시작했습니다.저는 C가 상당히 편합니다.malloc그리고.free개념, 하지만 코코아의 참조 계수 체계는 저를 다소 혼란스럽게 합니다.당신이 그것을 이해하면 그것은 매우 우아하다고 들었지만, 저는 아직 고비를 넘기지 않았습니다.

안녕하세요release,retain그리고.autorelease일과 그들의 사용에 대한 관습은 무엇입니까?

(아니면 실패했을 때, 무엇을 읽었길래 그것을 얻었습니까?)

먼저부터 retain그리고.release;autorelease기본 개념을 이해하면 정말 특별한 경우일 뿐입니다.

코코아에서 각 객체는 참조되는 횟수를 추적합니다(특히,NSObject기본 클래스는 이를 구현합니다.전로화에 으로써.retain개체에 대해 참조 카운트를 하나씩 올리고 싶다고 말합니다.전로화에 으로써.release개체를 놓으면 개체의 참조 카운트가 감소합니다. 만약을 부른 에, 전를건후에화에후건,▁if▁calling.release이제 참조 카운트가 0이 되면 시스템에서 해당 개체의 메모리가 해제됩니다.

이 이과다기방인법과 다른 입니다.malloc그리고.free즉, 시스템의 다른 부분이 손상될 염려가 없다는 것입니다. 시스템이 사용하던 메모리를 확보했기 때문입니다.모든 사용자가 규칙에 따라 게임을 수행하고 유지/해제한다고 가정할 때, 한 코드 조각이 개체를 유지했다가 해제할 때 개체를 참조하는 다른 코드 조각은 영향을 받지 않습니다.

때때로 혼란스러울 수 있는 것은 당신이 전화해야 하는 상황을 아는 것입니다.retain그리고.release제 일반적인 경험칙은 만약 제가 어떤 개체에 일정 시간 동안 매달리고 싶다면(예를 들어, 클래스의 구성원 변수인 경우), 그 개체의 참조 카운트가 저에 대해 알고 있는지 확인해야 합니다.는 위서설명객참체카조호의증다니가해합출에운는트에의한retain일반적으로 "init" 메서드를 사용하여 개체를 만들 때 개체가 증가합니다(실제 1로 설정됨).두 경우 모두 전화를 하는 것은 제 책임입니다.release내가 그것을 다 끝냈을 때 그 물체 위에.그렇지 않으면 메모리 누수가 발생할 것입니다.

객체 생성의 예:

NSString* s = [[NSString alloc] init];  // Ref count is 1
[s retain];                             // Ref count is 2 - silly
                                        //   to do this after init
[s release];                            // Ref count is back to 1
[s release];                            // Ref count is 0, object is freed

, 이제 은음다입니다.autorelease자동 해제는 시스템이 잠시 후 이 개체를 해제하도록 지시하는 편리한(때로는 필요한) 방법으로 사용됩니다.배관의 관점에서 볼 때,autorelease의 호됨출, 스드레의현입니다.NSAutoreleasePool통화를 알립니다.NSAutoreleasePool이제 기회를 얻으면(이벤트 루프의 현재 반복 후), 호출할 수 있음을 알 수 있습니다.release그 물건에프로그래머로서의 우리의 관점에서, 그것은 호출을 처리합니다.release우리를 위해, 그래서 우리는 그럴 필요가 없습니다 (그리고 사실, 우리는 하지 말아야 합니다).

주의해야 할 점은 (관습적으로) 모든 객체 생성 클래스 메서드가 자동으로 릴리스된 객체를 반환한다는 것입니다.예를 들어, 다음 예제에서 변수 "s"의 기준 카운트는 1이지만 이벤트 루프가 완료된 후에는 삭제됩니다.

NSString* s = [NSString stringWithString:@"Hello World"];

당신이 끈을 , 그끈붙고싶면다합, 해니다야를전화잡을다합니,▁를 불러야 합니다.retain에 명시적으로,으로, 그고명으로시적리로으명적시.release당신이 끝나면요.

다음과 같은 (매우 인위적인) 코드를 고려하면 다음과 같은 상황을 볼 수 있습니다.autorelease필수 항목:

- (NSString*)createHelloWorldString
{
    NSString* s = [[NSString alloc] initWithString:@"Hello World"];

    // Now what?  We want to return s, but we've upped its reference count.
    // The caller shouldn't be responsible for releasing it, since we're the
    // ones that created it.  If we call release, however, the reference 
    // count will hit zero and bad memory will be returned to the caller.  
    // The answer is to call autorelease before returning the string.  By 
    // explicitly calling autorelease, we pass the responsibility for
    // releasing the string on to the thread's NSAutoreleasePool, which will
    // happen at some later time.  The consequence is that the returned string 
    // will still be valid for the caller of this function.
    return [s autorelease];
}

저는 이 모든 것이 약간 혼란스럽다는 것을 알고 있습니다. 하지만 어느 순간, 그것은 찰칵찰칵 소리를 낼 것입니다.다음은 몇 가지 참고 자료입니다.

  • 애플의 메모리 관리 도입
  • Aaron Hillegas의 Mac OS X용 코코아 프로그래밍(4판) - 훌륭한 사례가 많은 매우 잘 쓰여진 책입니다.그것은 튜토리얼처럼 읽힙니다.
  • 만약 당신이 진정으로 다이빙을 한다면, 당신은 빅 너드 목장으로 향할 수 있습니다.위에서 언급한 책의 저자인 아론 힐레가스가 운영하는 훈련 시설입니다.저는 몇 년 전에 그곳에서 코코아 입문 과정을 수강했는데, 그것은 배울 수 있는 좋은 방법이었습니다.

보유/해제 과정을 이해한다면 기존 코코아 프로그래머들에게 명백한 두 가지 황금 규칙이 있지만, 안타깝게도 새로 온 사람들을 위해 이것을 명확하게 설명하는 경우는 거의 없습니다.

  1. 가 객를반는함수에를 가지고 있다면,alloc,create또는copy그것의 이름으로 그 물체는 당신의 것입니다.에 전화해야 .[object release]당신이 그것을 다 끝내면.또는CFRelease(object)Core-Foundation 주식회사.

  2. 이름에 이러한 단어 중 하나가 없으면 개체는 다른 사용자의 것입니다.에 전화해야 .[object retain]기능이 종료된 후에도 개체를 유지하려는 경우.

사용자가 직접 만든 기능에 대해서도 이 규칙을 따르는 것이 좋습니다.

(니트피커:예, 안타깝게도 이러한 규칙의 예외인 API 호출이 몇 개 있지만 거의 없습니다.

데스크톱용 코드를 작성하고 Mac OS X 10.5를 대상으로 할 수 있다면 Objective-C 가비지 컬렉션을 사용하는 방법을 알아봐야 합니다.이것은 개발의 대부분을 단순화할 것입니다. 그래서 Apple은 처음부터 개발을 시작하고 성능을 좋게 하기 위해 모든 노력을 기울였습니다.

GC를 사용하지 않을 때의 메모리 관리 규칙:

  • 을 를 생성합니다.+alloc/+allocWithZone:,+new,-copy또는-mutableCopy또는 당신이-retain.-release.
  • 다른 방법으로 개체를 수신하는 경우 사용자는 해당 개체의 소유자가 아니므로 개체가 전송되었는지 확인하면 안 됩니다.-release.
  • 이 물건을 확실히 개체전는확인는려경우하지었송되가▁if경.-release은 그것을, 수도 .-autorelease현재 자동 해제 풀이 이를 전송합니다.-release (※1회-autorelease)이) 수영장의 물이 빠집니다.

으로 일으로적.-autorelease에서는 개체가 현재 이벤트 기간 동안 계속 유지되도록 하는 방법으로 사용되지만 이후에는 코코아의 이벤트 처리를 둘러싸고 있는 자동 릴리스 풀이 있기 때문에 정리됩니다.코코아에서는 자동으로 릴리스된 개체를 호출자에게 반환하는 것이 호출자 자신이 릴리스해야 하는 개체를 반환하는 것보다 훨씬 일반적입니다.

목표-C는 참조 카운트를 사용합니다. 이는 각 개체에 참조 카운트가 있음을 의미합니다.개체가 생성되면 "1"의 참조 카운트를 가집니다.간단히 말해, 객체가 참조될 때(즉, 어딘가에 저장될 때) "유지"됩니다. 즉, 참조 카운트가 1씩 증가합니다.개체가 더 이상 필요하지 않으면 "해제"됩니다. 즉, 개체의 참조 수가 1만큼 감소합니다.

개체의 참조 수가 0이면 개체가 해제됩니다.이것은 기본 참조 카운트입니다.

일부 언어의 경우 참조가 자동으로 증가 및 감소하지만 objective-c는 이러한 언어 중 하나가 아닙니다.따라서 프로그래머는 유지 및 해제를 담당합니다.

메소드를 작성하는 일반적인 방법은 다음과 같습니다.

id myVar = [someObject someMessage];
.... do something ....;
[myVar release];
return someValue;

코드 내부에서 획득한 리소스를 해제해야 하는 문제는 지루하고 오류가 발생하기 쉽습니다.목표-C는 이를 훨씬 더 쉽게 만드는 것을 목표로 하는 또 다른 개념을 소개합니다.풀 자동 릴리스.자동 릴리스 풀은 각 스레드에 설치되는 특수 개체입니다.NSAuto releasePool을 찾아보면 꽤 간단한 클래스입니다.

개체가 "자동 해제" 메시지를 받으면 개체는 이 현재 스레드에 대한 스택에 있는 자동 해제 풀을 찾습니다.이 개체는 일반적으로 풀 자체가 해제되는 미래의 어느 시점에 "해제" 메시지를 보낼 개체로 목록에 개체를 추가합니다.

위의 코드를 사용하여 다음과 같이 말하면 더 짧고 읽기 쉽도록 다시 작성할 수 있습니다.

id myVar = [[someObject someMessage] autorelease];
... do something ...;
return someValue;

개체가 자동으로 릴리스되므로 더 이상 "해제"를 명시적으로 호출할 필요가 없습니다.이는 일부 자동 해제 풀이 나중에 이 기능을 수행할 것이라는 것을 알고 있기 때문입니다.

이게 도움이 되길 바랍니다.위키백과 기사는 참조 집계에 대해 꽤 잘 알고 있습니다.자동 릴리스 풀에 대한 자세한 내용은 여기에서 확인할 수 있습니다.또한 Mac OS X 10.5 이상용으로 빌드하는 경우 Xcode에 가비지 컬렉션을 사용하도록 설정하여 유지/릴리스/자동 릴리스를 완전히 무시할 수 있습니다.

Joshua (#6591) - Mac OS X 10.5의 가비지 컬렉션 항목은 꽤 멋진 것 같지만 iPhone에서는 사용할 수 없습니다(또는 10.5 이전 버전의 Mac OS X에서 앱을 실행하려는 경우).

또한 라이브러리나 재사용 가능한 것을 작성하는 경우, GC 모드를 사용하면 코드를 사용하는 모든 사용자가 GC 모드를 사용하도록 잠기므로 널리 재사용 가능한 코드를 작성하려는 사용자는 수동으로 메모리를 관리하는 경향이 있습니다.

언제나처럼, 사람들이 참조 자료를 다시 쓰려 할 때 그들은 거의 항상 무언가를 잘못 이해하거나 불완전한 설명을 제공합니다.

Apple은 코코아용 메모리 관리 프로그래밍 가이드에 코코아의 메모리 관리 시스템에 대한 전체 설명을 제공하며, 마지막에는 메모리 관리 규칙에 대한 간략하지만 정확한 요약이 있습니다.

50달러를 지불하고 힐레그스 책을 구입하는 것을 생각하는 것 외에 보유/해제에 대한 구체적인 사항은 추가하지 않겠지만, 애플리케이션 개발 초기에 Instruments 도구를 사용하는 것이 좋습니다.이렇게 하려면 [실행] -> [성능 도구로 시작]을 클릭합니다.먼저 Leaks에 대해 말씀드리겠습니다. Leaks는 사용 가능한 여러 기기 중 하나에 불과하지만 릴리스하는 것을 잊었을 때 보여주는 데 도움이 될 것입니다.얼마나 많은 정보를 제공받을 것인지는 상당히 벅찬 일입니다.빨리 이해 보세요: 튜토리얼을통해신시게작수있다이습니할하속▁but다이.
튜토리얼:: 메모리 누수 해결: 메모리 누수 해결

사실 유출을 강제로 막으려고 하는 것이 결국 유출을 예방하는 방법을 배우는 더 좋은 방법일 수도 있습니다!행운을 빌어요 ;)

맷 딜라드는 다음과 같이 썼습니다.

[자동 릴리스] 릴리스를 반환합니다.

자동 해제는 개체를 유지하지 않습니다.자동 릴리스는 나중에 릴리스할 대기열에 넣기만 하면 됩니다.여기에 릴리스 문을 지정하지 않을 수 있습니다.

코코아 메모리 관리 기사를 자주 수집합니다.

코코아 메모리 관리

iDeveloper에서 무료 스크린캐스트를 이용할 수 있습니다.TV 네트워크

Objective-C에서의 관리

NilObject의 답변은 좋은 시작입니다.다음은 수동 메모리 관리와 관련된 몇 가지 추가 정보입니다(iPhone에 필요).

당신이 개인적으로alloc/init개체는 1의 참조 카운트와 함께 제공됩니다.더 이상 필요하지 않을 때는 전화로 정리해야 합니다.[foo release]또는[foo autorelease]릴리스는 개체를 즉시 정리하는 반면, 자동 릴리스는 개체를 자동 릴리스 풀에 추가하여 나중에 자동으로 릴리스합니다.

자동 릴리스는 주로 문제의 객체를 반환해야 하는 메서드가 있지만(그래서 수동으로 해제할 없고, 그렇지 않으면 0 객체를 반환하게 될 이다) 보유하고 싶지 않을 때 사용됩니다.

alloc/init를 호출하여 가져오지 않은 개체를 획득하는 경우 예:

foo = [NSString stringWithString:@"hello"];

하지만 이 물체를 붙잡고 싶다면 [foo retain]을 불러야 합니다.그렇지 않으면, 그것은 가능성이 있습니다.autoreleased그리고 위의 예에서와 같이 제로 참조를 유지하게 됩니다.더 이상 필요하지 않을 때 전화하세요.[foo release].

위의 답변은 문서가 말하는 것에 대한 명확한 설명을 제공합니다. 대부분의 새로운 사람들이 마주치는 문제는 문서화되지 않은 사례입니다.예:

  • 자동 릴리스: 문서는 "미래의 어느 시점에서" 릴리스를 트리거할 것이라고 말합니다. 언제?!기본적으로 코드를 시스템 이벤트 루프로 다시 종료할 때까지 객체가 주변에 있을 것으로 기대할 수 있습니다.시스템은 현재 이벤트 사이클 후 언제든지 개체를 해제할 수 있습니다.(내 생각에 Matt는 아까 그렇게 말했습니다.)

  • 정적 문자열:NSString *foo = @"bar";당신은 그것을 유지하거나 해제해야 합니까?요. 그럼.

    -(void)getBar {
        return @"bar";
    }
    

    ...

    NSString *foo = [self getBar]; // still no need to retain or release
    
  • 작성 규칙:사용자가 작성한 경우 사용자가 소유하고 릴리스해야 합니다.

이 되는 하지 못하는 입니다.retainCount > 0.

다음은 코코아의 메모리 관리를 위한 매우 간단한 규칙의 일부입니다.

보존 수 규칙

  • 주어진 블록 내에서 -copy, -alloc 및 -retain의 사용은 -release 및 -autorerelease의 사용과 같아야 합니다.
  • 편의 생성자를 사용하여 생성된 개체(예: NSString의 stringWithString)는 자동 릴리스된 것으로 간주됩니다.
  • -dealloc 방법을 구현하여 소유한 인스턴스 변수를 해제합니다.

첫 번째 총알은 다음과 같이 말합니다: 만약 당신이 전화했다면.alloc(또는)new fooCopy.), 를 참조하십시오.

두 번째 글머리 기호는 다음과 같습니다. 편의 장치를 사용하는 경우 (나중에 그릴 이미지와 같이) 물건을 가지고 있어야 합니다(나중에 놓으면 됩니다.

세 번째는 스스로 설명할 수 있어야 합니다.

cocoadev에 대한 많은 좋은 정보도 있습니다.

이미 몇몇 사람들이 언급했듯이, Apple의 Intro to Memory Management는 시작하기에 가장 좋은 장소입니다.

아직 언급하지 않은 유용한 링크 중 하나는 실용적인 메모리 관리입니다.애플 문서를 훑어보면 중간쯤에서 찾을 수 있겠지만, 직접 연결해 볼 만한 가치가 있습니다.예와 일반적인 실수(기본적으로 여기에 있는 다른 답변이 설명하려고 하는 것은 아니지만)가 포함된 메모리 관리 규칙의 훌륭한 요약입니다.

언급URL : https://stackoverflow.com/questions/6578/understanding-reference-counting-with-cocoa-and-objective-c

반응형