AutoreleasePool 분석

16144 단어 대상

전언


AutoreleasePool 자동 방출 풀은 객체를 자동으로 방출하는 데 어떤 역할을 합니까?방출지 중의 자동 방출 대상은 언제 방출됩니까?

MRC 환경에서


장면 1

NSString *string_var_ = nil;
- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *string = [NSString stringWithFormat:@"bluefish"];
    string_var_ = string;

    NSLog(@"viewDidLoad--string: %@", string);
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    NSLog(@"viewWillAppear--string: %@", string_var_);
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    NSLog(@"viewDidAppear--string: %@", string_var_);
}

콘솔 인쇄:
viewDidLoad--string: bluefish
viewWillAppear--string: bluefish

그리고 NSLog(@"viewDidAppear--string: %@", string_var_); 야지침이 틀렸다.그 중에서 NSString *string = [NSString stringWithFormat:@"bluefish"];는 자동 방출 대상이고 인용 계수는 1이다.string은 이를 인용한다.viewDidLoad와viewWillAppear가 되돌아올 때string 대상은release가 아니고viewDidAppear에 도착할 때release가 된다.즉,string 대상은viewWillAppear와viewDidAppear 사이에 라인이 있는 자동 방출지release이다.
그러면string이 자동으로 풀리지 않으면,
NSString *string = [[NSString alloc] initWithFormat:@"%@",@"bluefish"];

세 가지 방법이 모두 인쇄될 수 있으나string은 명시적으로relase 방법을 호출하지 않았기 때문에string설이 인용한 [[NSString alloc] initWithFormat:@"%@",@"bluefish"]이 방출되지 않고 수동 메모리 관리 원칙에 부합되지 않는다.

장면 2


autoreleasepool을 사용하여 풀을 명시적으로 풀면 코드:
- (void)viewDidLoad {
@autoreleasepool {
        NSString *string = [NSString stringWithFormat:@"bluefish"];
        string_var_ = string;
    }
NSLog(@"viewDidLoad--string: %@", string_var_);
}

집행 후 NSLog(@"viewDidLoad--string: %@", string_var_); 야지침이 틀렸다.설명, autorelease 생성 시(인용 계수 1), autoreleasepool {} 자동 방출 탱크에 자동으로 추가되며, 끝날 때 안의 자동 방출 대상을 한 번release(인용 계수 -1)로 하기 때문에stringvar_야생 지침이 되고 국부 변수string 작용역이 종료되면 소각(출고)되므로 로그 인쇄 시stringvar_야외 지침이 틀렸다.
그러면 autoreleasepool의 비autorelease 대상이 풀리지 않을까요?
@autoreleasepool {
        NSString *string = [[NSString alloc] initWithFormat:@"%@",@"bluefish"];
        string_var_ = string;
    }

그 결과 세 가지 방법이 모두 인쇄되었는데, 이것은 autorelease 대상이 아니면 autoreleasepool에 가입하지 않는다는 것을 설명한다.그 상황은'장면1'과 마찬가지로string은 계속 풀리지 않는다.

장면 3


autoreleasepool 자동 방출 탱크를 현식으로 사용하고,string을 autoreleasepool {} 외에 정의하면 어떻게 됩니까?
- (void)viewDidLoad {
    [super viewDidLoad];

     NSString *string = nil;
    @autoreleasepool {
        string = [NSString stringWithFormat:@"bluefish"];
        string_var_ = string;
    }

    NSLog(@"viewDidLoad--string: %@", string_var_);
}

실행 후, 상황은 '장면 2' 와 같이 인쇄에 성공할 수 없습니다. 야외 바늘이 잘못되었습니다. [NSString stringWithFormat:@"bluefish"] 는 자동 방출 대상이기 때문에string은 이를 인용합니다. autoreleasepool {} 이 나오면string이 가리키는 [NSString stringWithFormat:@"bluefish"] 는 방출됩니다.string과stringvar_모두 들 지침이 되었다.그럼 [[NSString alloc] initWithFormat:@"%@",@"bluefish"]로 바꾸면 어떨까. 답은'장면2'와 마찬가지로 대상 인용은 계속 유효하다. 왜냐하면release가 없기 때문이다.
소결: 일반적인 상황에서 만들어진 autorelease 대상은 자신과 가장 가까운 방출 탱크에 추가됩니다. autoreleasepool {}을 현저하게 사용하지 않으면 현재 라인의 방출 탱크에 추가됩니다.일단 풀을 풀면 안의 대상은release를 한 번씩 한다.autoreleasepool {}을 현저하게 사용하더라도, 안의 비자동 방출 대상은 수동release를 사용해야 합니다. 그렇지 않으면 대상이 계속 방출되지 않습니다.
이상은 MRC(수동 메모리 관리)에서 자동적으로 탱크 autoreleasepool의 대상에 대한 처리 차이입니다.근데 ARC에서는 어떻게 될까요?

ARC 환경에서


장면 1


여기는 저희가 사용한weak 코스메틱 아웃소싱 변수stringweak,arc의 규칙에 따라stringweak_그가 인용한 대상을 소지하지 않으면 인용한 대상의 방출에 영향을 주지 않으며, 응용 대상이 방출될 때stringweak_자동으로 nil로 설정되므로 약한 인용 변수stringweak_대상의 방출을 관찰하고 코드를 보십시오.
__weak NSString *string_weak_ = nil;

- (void)viewDidLoad {
    [super viewDidLoad];

    //    1
    NSString *string = [NSString stringWithFormat:@"bluefish"];
    string_weak_ = string;

    NSLog(@"viewDidLoad--string: %@", string_weak_);
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    NSLog(@"viewWillAppear--string: %@", string_weak_);
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    NSLog(@"viewDidAppear--string: %@", string_weak_);
}

수행 후 콘솔 입력:
viewDidLoad--string: bluefish
viewWillAppear--string: bluefish
viewDidAppear--string: (null)

인쇄 인터페이스에서string 대상이viewWillAppear와viewDidAppear 사이에서 방출되는 것을 볼 수 있습니다.이 석방 시기는 MRC 아래와 같다. 단지 MRC 아래가 야외 지침으로 변해 잘못 보고했을 뿐이다.이해방식이 달라졌어요.[NSString stringWithFormat:@"bluefish"] 창설 시 해당 라인의 자동 방출 탱크에 자동으로 가입되어 방출은 방출 탱크에 맡겨 관리한다.그리고string은 그것을 인용합니다.arc에서 기본값은 이기 때문입니다.strong, 그래서 string은 그것을 강제로 인용했다.그러나string에서viewDidLoad 방법이 나오면 국부 변수string이 삭제됩니다. 이때string대[NSString stringWithFormat:@"bluefish"]에 대한 강한 인용은 사라지지만[NSString stringWithFormat:@"bluefish"]는 자동 방출 탱크에서 풀리지 않기 때문에string현재 라인이 자동으로 풀을 방출할 때까지 weak를 인용할 수 있습니다. [NSString stringWithFormat:@"bluefish"]그렇다면 비자동 방출 대상이라면:
NSString *string = [[NSString alloc] initWithFormat:@"%@",@"bluefish"];

인쇄 결과 실행하기
 viewDidLoad--string: bluefish
 viewWillAppear--string: (null)
 viewDidAppear--string: (null)

그 결과 [[NSString alloc] initWithFormat:@"%@",@"bluefish"]viewDidLoad 방법을 떠나자마자 풀려났다.[[NSString alloc] initWithFormat:@"%@",@"bluefish"]는 비자동 방출 대상이기 때문에 만들 때 자동 방출 탱크에 들어가지 않기 때문에 그의 방출은arc 메커니즘에서 강인용 대상string이 작용역을 떠날 때 소각되고 [[NSString alloc] initWithFormat:@"%@",@"bluefish"]는 모든 강인용을 잃으며 강인용 대상이 그것을 가리키지 않기 때문에arc는release를 실시했다.

장면 2


autoreleasepool을 사용하여 풀을 명시적으로 자동 해제합니다. 코드:
- (void)viewDidLoad {
    [super viewDidLoad];

    @autoreleasepool {
        NSString *string = [NSString  stringWithFormat:@"bluefish"];
        string_weak_ = string;
    }
    NSLog(@"viewDidLoad--string: %@", string_weak_);
}

인쇄 결과 실행하기
 viewDidLoad--string: (null)
 viewWillAppear--string: (null)
 viewDidAppear--string: (null)

결과적으로 [NSString stringWithFormat:@"bluefish"] autoreleasepool {}이 나오자마자 풀려났다.분석해 보면'장면1'과 마찬가지로 [NSString stringWithFormat:@"bluefish"] 창설할 때 자동적으로 autoreleasepool {} 자동 방출 탱크에 추가되어 방출 탱크에 맡겨 관리한다.그리고string은 그에 대해 강력한 인용을 하고 string은 autoreleasepool {}에서 정의한 것이다. autoreleasepool {}이 끝날 때string은 소각되고 강한 인용은 사라진다. 이때 autoreleasepool {} 자동 방출 탱크도 끝났기 때문[NSString stringWithFormat:@"bluefish"]도 방출되었다.
그럼 비자동 방출 대상으로 바뀌면,
 @autoreleasepool {
        NSString *string = [[NSString alloc] initWithFormat:@"%@",@"bluefish"];
        string_weak_ = string;
    }

인쇄 결과는 여전히 같습니다, why?다음은 [[NSString alloc] initWithFormat:@"%@",@"bluefish"]가 자동으로 방출되지 않기 때문에 autoreleasepool에 가입하지 않고 arc로 메모리를 관리하고string은 이를 강력하게 인용한다.그러나 autoreleasepool {}이 끝날 때 국부 변수string은 삭제되고arc에서 [[NSString alloc] initWithFormat:@"%@",@"bluefish"]는 강력한 인용을 잃으면 방출됩니다.그래서 마지막 autoreleasepool {}이 모두 풀려났습니다.
PS: lldb 명령을 사용하여 watchpoint set v stringweak_ 관찰점 설정, 관찰stringweak_ 변수의 값 변화.중단점을 설정하고 watchpoint set v stringweak_ ,stringweak_변경(nil)이 감지됩니다.
watchpoint set v string_weak_
Watchpoint created: Watchpoint 1: addr = 0x000978e0 size = 4 state = enabled type = w
    declare @ '/Users/Bluefish/Documents/textPro/AutoreleasePoolTest/AutoreleasePoolTest/ViewController.m:15'
    watchpoint spec = 'string_weak_'
    new value: 0x7a160340

Watchpoint 1 hit:
old value: 0x7a160340
new value: 0x00000000

장면 3


autoreleasepool 자동 방출 탱크를 현식으로 사용하고string을 autoreleasepool {} 외에 다음과 같이 정의합니다
- (void)viewDidLoad {
    [super viewDidLoad];

    NSString *string = nil;
    @autoreleasepool {
        string = [NSString stringWithFormat:@"bluefish"];
        string_weak_ = string;
    }

    NSLog(@"viewDidLoad--string: %@", string_weak_);
}

실행 결과:
viewDidLoad--string: bluefish
viewWillAppear--string: (null)
viewDidAppear--string: (null)

autoreleasepool {}을 내보낸 후에도 출력이 가능한지 이상할 수도 있습니다. [NSString stringWithFormat:@"bluefish"] 풀리지 않았습니다.아래 분석, [NSString stringWithFormat:@"bluefish"] 창설 시 autoreleasepool 방출 탱크에 가입하여string은 그에 대한 강한 인용을 한다. autoreleasepool {}이 끝날 때[NSString stringWithFormat:@"bluefish"]는 방출되지만 string은 그 작용 영역 내에 있기 때문에 [NSString stringWithFormat:@"bluefish"]에 대한 강한 인용을 계속하기 때문에viewDidLoad {}가 끝날 때까지string은 소각되고 강한 인용은 사라진다.arc에서어떤 강력한 인용도 잃은 [NSString stringWithFormat:@"bluefish"] 는 결국 석방되었다.
그렇다면 자동 해제되지 않은 대상은 다음과 같다.
NSString *string = nil;
    @autoreleasepool {
        string = [[NSString alloc] initWithFormat:@"%@",@"bluefish"];
        string_weak_ = string;
    }

인쇄 결과를 실행하는 것도 마찬가지다.여기서 autoreleasepool {} 자동 방출 탱크는 사실 아무런 실제 작용도 하지 못한다.다음은 [[NSString alloc] initWithFormat:@"%@",@"bluefish"]가 만들어졌을 때 자동 방출 대상이 아니기 때문에 autoreleasepool의 자동 방출 탱크에 가입하지 않을 것이다. 즉, 그의 메모리 관리는 arc가 처리하고string은 이를 강력하게 인용한다. autoreleasepool {}이 끝날 때 방출 탱크에 방출 가능한 대상이 없고string도 그 역할 영역에 있기 때문에 autoreleasepool {}는 아무것도 하지 않았다.viewDidLoad {}가 끝날 때까지.string 소각[[NSString alloc] initWithFormat:@"%@",@"bluefish"]은 강력한 인용을 잃고 결국 석방됩니다.
소결:arc 환경에서 autoreleasepool {} 역시 자동 방출 대상만 관리하고 autoreleasepool {}이 끝날 때 자동으로 풀의 대상을 방출합니다.그러나arc 메커니즘의 존재로 인해autoreleasepool{}의 기능은 사실상 약화된 것으로 볼 수 있다. 그의 역할은 더욱arc 환경에서 자동 대상의 방출 시기를 제어하는 데 사용된다. 예를 들어'장면2'이다.

총결산


자동 방출 대상만 가장 가까운 자동 방출 탱크에 가입하고 자동 방출 탱크가 끝날 때 탱크의 대상은 한 번 방출된다.로컬 변수는 역할 영역이 끝나면 삭제됩니다.
일반적으로 프로그램의 자동 방출 대상(alloc new copy 또는 MRC에서 autorelease 사용)은 현재 스레드의 자동 방출 탱크에 추가됩니다. (스레드마다 기본 자동 방출 탱크가 있습니다) 이 스레드가 끝날 때 자동 방출 탱크의 대상은 삭제됩니다.'장면 1'을 참고하십시오.따라서 autoreleasepool {}을 현저하게 사용하지 않았을 때, 프로그램의 자동 방출 대상은 여전히 은밀한 자동 방출 탱크에 있습니다. (프로그램은 실행 중인 각 라인에 있으며, 주 라인을 포함합니다.)
MRC에서는 참조 개수의 개념을 사용하여 메모리를 관리합니다.하나의 대상이 만들어지면 인용 계수가 1이 됩니다. 만들어지면 다른 일반적인 대상 포인터 변수를 사용해서 대상을 가리킬 수 있습니다. arc와 달리 이 대상을 가리키는 인용 계수는 바뀌지 않습니다. 대상에게retain이나copy (얕은 복사) 계수 +1을 보내지 않으면 만들어진 대상은 alloc new copy를 통해 만들어집니다. 자동 방출 대상을 제외하고는 마지막으로release 방법을 보내야 합니다.따라서 마지막으로 MRC에서 autoreleasepool {}에 만들어진 비자동 방출 대상은release 방법을 사용해야 한다는 준칙을 기억하면 됩니다.autoreleasepool {}에서 만든 자동 방출 대상은 autoreleasepool이 끝나면 release에 의해 한 번 인용됩니다.
ARC에서 메모리 관리는 대상의 강약 인용으로 처리되며, 한 대상은 모든 강약 인용을 잃으면 소각되고, 약인용은 자동으로 nil로 설정됩니다.ARC에서 작성된 객체는 두 가지 다른 메모리 처리 모드로 볼 수 있습니다.메모리 관리는arc에서 처리하는 비자동 방출 대상하나는 자동 방출 대상이고 메모리 관리는 자동 방출 탱크에서 나온다.같은 이치로 autoreleasepool {}에서 만든 비자동 대상은 arc에서 처리하고, 자동 방출 대상은 현재 autoreleasepool에서 관리하지만, arc의 환경에서 autoreleasepool {}에서 만든 비자동 방출 대상이든, 자동 방출 대상이든, 마지막에 한 번 방출됩니다. (autoreleasepool {}의 비자동 방출 대상은 이 역할 범위가 끝날 때 arc에서 한 번 방출되기 때문입니다.)autoreleasepool {}이 끝날 때, 이 autoreleasepool {} 밖의 변수가 안에 만들어진 대상을 강하게 인용할 때, 이 대상은 계속 보존됩니다.

좋은 웹페이지 즐겨찾기