NSAutoreleasePool 자동 릴리스 풀은 어떻게 작동합니까?


95

내가 알기로는 alloc , new 또는 copy로 만든 모든 것은 수동으로 해제해야합니다. 예를 들면 :

int main(void) {
    NSString *string;
    string = [[NSString alloc] init];
    /* use the string */
    [string release];
}

내 질문은 이것이 유효하지 않습니까? :

int main(void) {
    NSAutoreleasePool *pool;
    pool = [[NSAutoreleasePool alloc] init];
    NSString *string;
    string = [[[NSString alloc] init] autorelease];
    /* use the string */
    [pool drain];
}

답변:


68

예, 두 번째 코드 조각은 완벽하게 유효합니다.

-autorelease가 객체로 전송 될 때마다 가장 안쪽의 autorelease 풀에 추가됩니다. 풀이 배수되면 풀의 모든 오브젝트에 -release를 전송합니다.

Autorelease 풀은 단순히 "나중에"까지 보내기를 연기 할 수있는 편리함을 제공합니다. 이 "나중에"는 여러 곳에서 발생할 수 있지만 Cocoa GUI 앱에서 가장 일반적인 것은 현재 실행 루프주기의 끝입니다.


5
루프가없는 경우 현재 실행 루프주기의 끝은 어디입니까?
감사합니다

24
"가장 바깥 쪽"이 "가장 안쪽"이어야하지 않습니까?
Mike Weller

an object이어야합니다 an object that is a subclass of NSObject or NSProxy and doesn't override -autorelease.

1
편집 : 가장 바깥 쪽을 안쪽으로 변경했습니다.
chakrit 2011

1
중요 : ARC (Automatic Reference Counting)를 사용하는 경우 자동 릴리스 풀을 직접 사용할 수 없습니다. 대신 @autoreleasepool 블록을 사용합니다. 에서 developer.apple.com/library/mac/#documentation/Cocoa/Reference/...
메릴랜드 마버 부르 라흐만

37

NSAutoreleasePool : 드레인 대 릴리스

의 기능 때문에 drain하고 release혼란을 일으키는 것 같다, 그것은 (이이 덮여 있지만 가치는 여기에 명확히 수 있습니다 문서 ...).

엄밀히 큰 그림의 관점에서 말하는 것은 drain입니다 하지 동일합니다 release:

참조 횟수가 계산 된 환경에서는와 drain동일한 작업을 수행 release하므로 두 가지가 동일한 의미입니다. 강조하기 위해,이 방법은 당신이 할 수 없습니다 당신이 사용하는 경우 풀을 누설 drain보다는 release.

가비지 수집 환경에서는 작동 release하지 않습니다. 따라서 효과가 없습니다. drain반면에에는 수집가에게 "필요한 경우 수집"해야한다는 힌트가 포함되어 있습니다. 따라서 가비지 수집 환경에서를 사용 drain하면 시스템 균형 수집 스위핑이 도움이됩니다.


4
.NET Framework를 '누출'하는 것은 근본적으로 불가능합니다 NSAutoreleasePool. 풀이 스택처럼 작동하기 때문입니다. 풀을 인스턴스화하면 해당 풀이 해당 스레드 자동 해제 풀 스택의 맨 위로 이동합니다. -release그 풀은 스택 그 위에 푸시 된 모든 풀 에서 팝 되지만 어떤 이유로 든 팝되지 않았습니다.
johne

7
이것이 내가 쓴 내용과 어떤 관련이 있습니까?
mmalc

2
나는 그가 대담하고 시간을 보내는 방법을 좋아합니다. 스냅!
Billy Gray

17

이미 지적했듯이 두 번째 코드 조각이 정확합니다.

모든 환경 (ref counting, GC, ARC)에서 작동하고 드레인 / 릴리스 혼동을 피하는 autorelease 풀을 사용하는보다 간결한 방법을 제안하고 싶습니다.

int main(void) {
  @autoreleasepool {
    NSString *string;
    string = [[[NSString alloc] init] autorelease];
    /* use the string */
  }
}

위의 예에서 @autoreleasepool 블록에 유의하십시오 . 여기에 설명되어 있습니다 .


2
ARC에서는 자동 릴리스가 허용되지 않습니다.
dmirkitanov

1
명확히하기 위해 @autoreleasepoolARC와 함께 블록 을 사용해야합니다 .
Simon

7

아니, 넌 틀렸어. 문서에는 비 GC에서 -drain이 -release와 동일하므로 NSAutoreleasePool이 유출 되지 않는다고 명시되어 있습니다.


그렇다면 Xcode가 -drain으로 코드를 생성하는 이유가 궁금했습니다. Xcode에서 생성 한 코드를 기반으로 -release와 동일하다고 생각했기 때문에 -drain을 사용했습니다.
James Sumners



0

객체에 릴리즈 대신 자동 릴리즈를 보내면 적어도 풀 자체가 비워 질 때까지 해당 객체의 수명이 연장됩니다 (객체가 나중에 유지되는 경우 더 길어질 수 있음). 오브젝트는 동일한 풀에 여러 번 배치 될 수 있으며,이 경우 풀에 배치 될 때마다 릴리스 메시지를 수신합니다.


-2

예, 아니오. 문자열 메모리를 해제하지만 가비지 수집 (메모리 관리가 아님) 환경에서이를 실행하면 해제 대신 drain을 사용하여 NSAutoreleasePool 개체를 메모리로 "누수"합니다. 이 "누수"는 GC 아래에 강력한 포인터가없는 다른 객체와 마찬가지로 NSAutoreleasePool의 인스턴스를 "도달 할 수 없음"으로 만들고 다음에 GC가 실행될 때 객체가 정리됩니다. 이는 다음을 호출 한 직후 일 수 있습니다 -drain.

배수

가비지 수집 환경에서 마지막 수집 이후 할당 된 메모리가 현재 임계 값보다 큰 경우 가비지 수집을 트리거합니다. 그렇지 않으면 릴리스로 작동합니다. ... 가비지 수집 환경에서이 메서드는 궁극적으로 objc_collect_if_needed.

그렇지 않으면 -release비 GC에서 작동 하는 방식과 유사 합니다. 다른 사람이 언급했듯이, -releaseGC 통해입니다 아래에있는 유일한 방법은 반드시 풀 제대로 작동 할 수 있도록 GC 아래에 어떤 조합이없는 -drain, 그리고 -drain비 GC에서 정확히 같은 작품 -release이 아닌 GC에서, 거의 틀림없이 더 명확로서의 기능을 통신 잘.

"init"는 메모리를 할당하지 않고 객체 (생성자) 만 설정하기 때문에 "new, alloc 또는 init로 호출 된 모든 것"에는 "init"가 포함되지 않아야합니다 (하지만 "복사"는 포함되어야 함). 패션). 할당 된 객체를 받고 함수가 init 만 호출 한 경우 해제하지 않습니다.

- (void)func:(NSObject*)allocd_but_not_init
{
    [allocd_but_not_init init];
}

그것은 이미 시작한 것보다 더 많은 메모리를 소비하지 않습니다 (init가 객체를 인스턴스화하지 않는다고 가정하지만 어쨌든 당신은 책임이 없습니다).


배수에 대한 귀하의 정보가 정확하지 않은 경우이 답변을 수락하는 것이 불편합니다. developer.apple.com/documentation/Cocoa/Reference/Foundation/…을 참조하십시오. 업데이트하면 다시 수락하겠습니다.
James Sumners

답장이 정확하지 않은 것은 무엇입니까? 가비지 수집 된 환경 (설명 된대로)에서 drain은 AutoReleasePool을 삭제하지 않으므로 release를 사용하지 않는 한 메모리 누출됩니다. 내가 나열한 인용구는 말의 입에서 바로 나온 것입니다.
Loren Segal

1
Loren : GC에서-[NSAutoreleasePool drain]은 컬렉션을 트리거합니다. -retain, -release 및 -autorelease는 모두 수집기에서 무시됩니다. 이것이 GC의 자동 릴리스 풀에서 -drain이 사용되는 이유입니다.
Chris Hanson

'드레인'에 대한 문서 : 관리되는 메모리 환경에서 이는 릴리스 호출과 동일하게 작동합니다. 따라서 릴리스 대신 '드레인'을 사용하면 메모리가 누출 되지 않습니다 .
mmalc

-[NSAutoreleasePool release]쓰레기 수거 환경에서는 작동하지 않습니다. -[NSAutoreleasePool drain]참조 횟수 및 가비지 수집 환경 모두에서 작동합니다.
Jonathan Sterling
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.