program story

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

inputbox 2020. 8. 27. 07:46
반응형

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


내가 알기로는 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];
}

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

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

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


NSAutoreleasePool : 드레인 대 릴리스

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

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

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

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


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

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

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

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


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


내가 Apple에서 읽은 내용 : "자동 해제 풀 블록이 끝날 때 블록 내에서 자동 해제 메시지를받은 객체는 해제 메시지를받습니다. 객체는 블록 내에서 자동 해제 메시지를 보낼 때마다 해제 메시지를받습니다. "

https://developer.apple.com/library/mac/documentation/cocoa/conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html


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


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

배수

In a garbage collected environment, triggers garbage collection if memory allocated since last collection is greater than the current threshold; otherwise behaves as release. ... In a garbage-collected environment, this method ultimately calls objc_collect_if_needed.

Otherwise, it's similar to how -release behaves under non-GC, yes. As others have stated, -release is a no-op under GC, so the only way to make sure the pool functions properly under GC is through -drain, and -drain under non-GC works exactly like -release under non-GC, and arguably communicates its functionality more clearly as well.

I should point out that your statement "anything called with new, alloc or init" should not include "init" (but should include "copy"), because "init" doesn't allocate memory, it only sets up the object (constructor fashion). If you received an alloc'd object and your function only called init as such, you would not release it:

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

That does not consume any more memory than it you already started with (assuming init doesn't instantiate objects, but you're not responsible for those anyway).

참고URL : https://stackoverflow.com/questions/65427/how-does-the-nsautoreleasepool-autorelease-pool-work

반응형