OC MRC 여행

3482 단어

OC MRC 여행


먼저 예를 들어 People 대상의 인용 계수를 계산해 보세요.
- (void)viewDidLoad {
    [super viewDidLoad];
    
    People *p = [[People alloc] init]; //
    
    People *p1 = [p retain]; //
    
    [p release]; //
    
    [p1 retain]; //
    
    NSLog(@"p:%ld", [p retainCount]);
    
    People *p2 = p;
    p2.firstName = [NSString stringWithFormat:@"%d ", 2];
    p2.lastName = [NSString stringWithFormat:@"%d ", 3];
    NSLog(@"%@", p2.firstName);
    
    [p2 release]; //
    [p2 release]; //
}

정답: 1, 2, 1, 2, 1, 0.
주의: 바늘은 단지 우리가 이 대상에 접근할 수 있도록 할 뿐입니다.p,p1,p2는 같은 대상을 가리키기 때문에 위의retain,release가 조작하는 것도 같은 대상이다.
People 클래스를 살펴보겠습니다.
@implementation People

@interface People : NSObject

@property (nonatomic, retain) NSString *firstName;
@property (nonatomic, retain) NSString *lastName;

@end

- (void)dealloc
{
    [_firstName release];
//    [_lastName release];
    
    NSLog(@"_firstName:%ld", [_firstName retainCount]); //1
    NSLog(@"_lastName:%ld", [_lastName retainCount]); //2
    
    [super dealloc];
}

- (void)setFirstName:(NSString *)firstName
{
    [firstName retain];
    [_firstName release];
    _firstName = firstName;
}

@end


위의 [_lastName release];를 주석하면 메모리 유출을 초래할 수 있습니다.왜 이런 상황을 초래했을까요?p2.lastName = [NSString stringWithFormat:@"%d ", 3];는 자동 방출 탱크에 등록된 대상이지만lastName 속성은retain이기 때문에 값을 부여할 때 이 문자열의 대상 인용 계수가 1이 증가하기 때문에 People 대상이 소각될 때lastName 문자열의 대상을 방출해야 합니다.MRC 환경에서 객체를 제거할 때는 일반적으로 자신의 속성을 해제해야 합니다.
People 대상이 소각되었을 때_firstName_lastName의 인용 계수 상황을 계속 살펴보면 인쇄_firstName는 1, _lastName는 2.왜 People의 - dealloc 방법_firstName의 인용 계수가 0이 아니라 1인가요?이것은 자동 방출 탱크가 아직 방출되지 않았기 때문에 그 안에 등록된 대상도 아직 방출되지 않았기 때문_firstName은 1._lastName의 경우 2.
주의: 한 대상은 같은 연못에 여러 번 넣을 수 있으며, 이 경우 한 번 놓을 때마다release 메시지를 받을 수 있습니다.
여기까지가 끝이라고 생각한다면 too young.문제는 아직 명확하지 않은 것 같다. 바로 자동 방출 탱크의 대상이 언제 방출되는가?공식 문서에서 @autorelease {...}에블록의 끝에 있는 자동 방출 탱크는drain이고 안의 대상은 방출됩니다.그러나 상술한 코드를 살펴보면 autorelease 블록을 보지 못했다.우리가 주 라인에 있기 때문에 주 라인의runloop이 기본적으로 켜져 있는 것을 보지 못했기 때문에, 어떻게 자동 방출 탱크가 라인과runloop에 연결되었는지 이상할 수도 있습니다.사실상 자동 방출지, 라인,runloop은 밀접한 관계를 가진다.
그러면 메인 라인의 자동 방출 탱크는 언제 만들고 언제 소각합니까?공식 문서에 따르면 Application Kit는 이벤트 순환의 모든 순환이 시작될 때 주 라인에 자동 방출 탱크를 만들고 순환이 끝날 때drains를 사용해서 이벤트를 처리할 때 생성된 자동 방출 대상을 방출합니다.Application Kit를 사용하는 경우 일반적으로 자체 풀을 만들 필요가 없습니다.그러나 만약 응용 프로그램이 이벤트 순환에 대량의 임시 자동 해제 대상을 만들었다면, '로컬' 자동 해제 풀을 만들어서 최대 메모리 사용을 최대한 줄이는 데 도움이 될 수 있습니다.공식 문서는 항상 이렇게 간결해서 사람들로 하여금 한참을 궁리하게 한다.제가 설명해 드릴게요. 메인 라인의 runloop은 기본적으로 켜져 있습니다. runloop도 하나의 순환이지만 일반적인 순환과 큰 차이가 있습니다. runloop은 라인이 할 일이 있을 때 일을 하고 할 일이 없을 때 라인을 휴면하게 합니다.runloop은 또 어떻게 할 일이 있다는 것을 알았을까?이것이 바로 우리가 사전에 runloop에 추가한 각종 원본이다.좀 멀어졌어, 더 얘기하면 주제에서 벗어날 것 같아.그래서 여기서 우리는 당분간 runloop이 어떻게 알았든지 간에 어쨌든 runloop은 알았다.프로그램이 시작되면 사용자가 화면을 클릭하면runloop에서 이 이벤트를 처리합니다.처리하기 전에 메인 라인의runloop은 자동 방출 탱크를 만들고 처리가 끝날 때 자동 방출 탱크drain을 생성합니다. 안의 대상은 방출되고 이벤트 처리가 끝나면runloop은 종료됩니다. 시스템이 다시 runloop으로 구동될까 봐 걱정하지 마세요.따라서 이벤트 순환에 대량의 임시 자동 방출 대상을 만들었다면, 스스로 수동으로 자동 방출 탱크를 만들어야 한다.그렇지 않으면 사건 처리가 끝나면 시스템에drain이 오게 하려고 합니다. 메모리가 이미 다 소모되었을 수도 있고 당신의 앱도 식사를 멈추게 될 것입니다.다행히 스스로 만드는 것은 번거롭지 않다@autorelease{...}.
오늘의 MRC 여행은 여기까지입니다.

참고 자료


Advanced Memory Management Programming Guide
NSAutoreleasePool

좋은 웹페이지 즐겨찾기