아이폰 개발(6) 메모리 유출 방지 방법

Objective-C는 이미 쓰레기 회수 메커니즘이 있지만 우리가 가장 관심을 가지는 iso는 쓰레기 회수를 지원하지 않기 때문에 진정하고 쓰레기 회수를 버리고 메모리를 스스로 관리합시다.
대상 소유권: 한 대상의 속성이 다른 대상일 때 다시 말하면 대상 A 중 하나의 속성이 대상 B이다. 그러면 대상 A가 대상 B에 대해 대상 소유권이 있다.그러면 대상 A가 방출될 때 우리는 대상 B의 인용 계수가 1로 줄어들도록 확보해야 한다(이곳은 방출 대상 B가 아니라 대상 B가 다른 곳에서 인용될 수 있기 때문이다).
매우 흔히 볼 수 있는 예는 set 방법으로 한 대상을 다른 대상의 속성으로 설정하는 것이다.여기서 우리는 인용 계수가 혼란스럽지 않고 다음과 같은 양호한 실현을 확보해야 한다.
//       Car     ,Engine    
-(void) setEngine:(Engine *) newEngine
{
    [newEngine retain];//  newEngine     ,   Car newEngine      
    [engine release];//    engine
    engine = newEngine;//    newEngine
}

자동 방출 탱크: 하나의 용기로 대상을 불러올 수 있으며, 탱크가 소각될 때, 동시에 모든 대상에게release 메시지를 보낼 수 있습니다. (여기는 직접 소각된 대상이 아니라release 메시지를 보낼 수 있습니다.)객체에 autorelease 메시지를 보낼 때 NSAutorelease에 객체를 실제로 추가합니다.자동 방출 탱크가 소각되면 대상에게release 메시지를 보냅니다.물론 자동 방출 탱크도 정상적인 Objective-C 대상이며 인용 계수 규칙을 준수한다.다음은 자동 방출 탱크의 작업 현상을 비교적 뚜렷하게 보여줄 수 있는 두 가지 예가 있다.
#import <Foundation/Foundation.h>

@interface RetainTracker : NSObject
@end 

@implementation RetainTracker

- (id) init
{
	if (self = [super init]) {
		NSLog (@"init: Retain count of %d.",
			   [self retainCount]);
	}
	
	return (self);
	
} 


- (void) dealloc
{
	NSLog (@"dealloc called. Bye Bye.");
	[super dealloc];
	
} 

@end




int main (int argc, const char * argv[])
{
    NSAutoreleasePool *pool;
    pool = [[NSAutoreleasePool alloc] init];
	
    RetainTracker *tracker;
    tracker = [RetainTracker new]; // count: 1
	
    [tracker retain]; // count: 2
    // tracker         
    [tracker autorelease]; // count: still 2
    [tracker release]; // count: 1
	
    NSLog (@"releasing pool");
    [pool release]; 
	
    return (0);
}
#import <Foundation/Foundation.h>

@interface RetainTracker : NSObject
@end 

@implementation RetainTracker

- (id) init
{
	if (self = [super init]) {
		NSLog (@"init: Retain count of %d.",
			   [self retainCount]);
	}
	
	return (self);
	
} 


- (void) dealloc
{
	NSLog (@"dealloc called. Bye Bye.");
	[super dealloc];
	
} 

@end




int main (int argc, const char * argv[])
{
    NSAutoreleasePool *pool;
    pool = [[NSAutoreleasePool alloc] init];
	
    RetainTracker *tracker;
    tracker = [RetainTracker new]; // count: 1
	
    [tracker retain]; // count: 2
    [tracker retain]; // count: 3

    // tracker         
    [tracker autorelease]; // count: still 3
    [tracker release]; // count: 2
	
    NSLog (@"releasing pool");
    [pool release]; 
	
    return (0);
}

독자는 스스로 두 단락의 코드의 출력을 비교해 보십시오.
코코아 메모리 관리 규칙:
1. new,alloc,copy 방법으로 대상을 만들 때 이 대상의 보존계수기 값은 1입니다.이 대상을 더 이상 사용하지 않을 때, 그 대상에게release나autorelease 메시지를 보내는 것을 책임져야 한다.이렇게 하면 대상은 사용 수명이 끝날 때 파괴될 것이다.
2. 다른 방법을 통해 대상을 얻을 때 그 대상이 정리될 수 있도록 어떤 조작도 할 필요가 없다.예를 들어 이런 문구: NSMutable Array *array = [NSMuable Array array With Capacity:17];array의 인용 계수를 유지할 필요가 없습니다. 시스템이 당신을 도와 완성할 것입니다. (자동 방출 탱크의 도움을 빌립니다.)물론, 만약 당신이 한동안 array를 가지려고 한다면, 인용 계수를 늘리고, 사용하지 않을 때 인용 계수를 줄여야 한다.
3. 만약 당신이 어떤 대상을 보류한다면 그 대상을 방출하거나 자동으로 방출해야 한다.retain 방법과release 방법의 사용 횟수를 동일하게 유지해야 합니다. (토론을 시작해야 하는 set 방법)
마지막으로 두 가지 문제를 설명한다.
1. 시작된 set 방법은 대상이 소각되지 않았을 때 그의 속성 대상도 소각되고 처리 방식은 간단하다. 대상의 dealloc 방법에서 속성 대상에게release를 보낸다.
2. 자동 방출 탱크도 함부로 사용할 수 있는 것이 아니다. 예를 들어 순환 중에 우리는 끊임없이 새로운 대상을 만들고 대상은 자동 방출 탱크에 불러온다.그러면 순환이 매우 클 때 자동 방출 탱크에 불러오는 대상이 방출되지 않고 우리의 프로그램이 차지하는 메모리가 지속적으로 증가할 것이다.이때의 처리 방법은 끊임없이 자신의 자동 방출 탱크를 만들고 방출(방출할 때 안의 대상도 따라서 방출)한 다음에 다시 만들고 방출하는 것이다.

좋은 웹페이지 즐겨찾기