[출처: http://maclove.pe.kr/32]

메모리 관리

많은 개발자들이 Objective-C 의 메모리 관리를 어렵게 느낀다. Objective-C 에서 객체는 참조 카운터를 이용해서 관리되기 때문에, 참조 카운터를 증가 시키고 감소하는 작업이 프로그래머의 몫이 된다. 여기서 혼돈이 오는 것이다. 참조 카운터를 증가시키는 함수는 retain 이다. 반대로 참조 카운터를 감소시키는 함수는 release와 autorelease 이다. 하지만 문제는 이미 만들어진 객체의 메서드가 내부에서 retain 을 몇번 부르는지를 별도로 알아낼 방법이 없다는 것이다. 다음을 보자.

UIImageView* imgView = [[UIImageView alloc] init];

이 코드에서 UIImageView 는 retain 내부에서 한번 호출해서 객체를 반환해 준다. 그렇기 때문에 우리는 더이상 필요하지 않을때,

[imgView release];

를 호출해야 한다. 하지만 다음을 보자.

NSString* output = [NSString stringWithFormat:@”My name : %@”, name];

이 코드는 NSString의 stringWithFormat 클래스 메서드를 이용해서 객체를 생성하는 코드이다. 이 녀석은 retain 이 아닌 autorelease 를 호출해서 객체를 반환한다. 이렇게 어떤 메서드는 객체를 retain 해서 반환하고, 또 어떤 객체는 autorelease 로 반환하기 때문에 혼돈이 온다.

참조 카운트를 관리하는 함수는 다음과 같다.

• retain
     - 참조 카운트를 1 증가 시킨다.
• release
     - 참조 카운트를 1 감소시킨다. 참조 카운트가 0이 되면 메모리가 해제된다.
• autorelease
     -  객체를 오토릴리즈 풀에 등록한다. 나중에 오토릴리즈 풀이 제거될때 release 를 호출해 준다.

객체의 참조를 관리하는 것은 위 3개의 메서드가 전부이지만, 문제는 클래스 내부 구현에서 위 함수들을 호출하는 지를 모른다는 점이다. 하지만 법칙이 있다. 애플이 작성한 모든 클래스는 정해진 규칙을 철저하게 따르기 때문에 이 법칙들만 알아두면 더 이상 햇갈릴 일이 없다.

* 규칙1 : alloc, copy, new를 이름에 포함하는 메서드는 retain 된 객체를 반환한다.

alloc, copy, new 가 메서드 이름에 포함되어 있다면, 그 때 반환되는 객체는 retain 되어 있다. 그래서 반드시 release 를 직접 호출해야 한다.

01: queue = [[NSOperationQueue alloc] init];
02: // 작업
03: [queue release];
04:
05: copyedObj = [name copy];
06: // 작업
07: [copyedObj release];

* 규칙2 : 결자해지

만약 자신이 retain 을 호출했다면, 책임지고 release 또는 autorelease 를 호출해 주자.

01: [objA retain];
02: // 작업
03: [objA release];

반드시 자신이 호출한 retain 에 대해서 release/autorelease 짝을 맞추도록 하자.

* 규칙3: 클래스 메서드가 객체를 생성해 줄때는 autorelease 객체를 반환한다.

클래스 메서드로 객체를 생성하는 경우 즉 stringWithFormat 과 같은 클래스 메서드가 반환하는 객체는 모두 autorelease 객체이다.

01: img = [UIImage imageNamed:@"test.png"];
02: imgView = [[UIImageView alloc] initWithImage:];
03: // 작업
04: [imgView release];

코드 1행의 imageNamed 메서드 처럼 클래스 메서드를 이용해서 객체를 생성하는 경우 그 객체는 autorelease 가 호출된 객체이다. 그렇기 때문에 별도로 release 를 호출하지 않아도 오토릴리즈 풀이 자동으로 release 를 호출해 준다. 하지만 이 객체에 retain 을 호출 했다면 호출한 만큼의 release 를 호출 해야한다.

* 규칙4: 포함 객체는 추가된 객체를 retain 하고, 항목을 제거할 때 release 한다.

NSArray,NSDictionay 등의 포함 객체는 항목으로 추가되는 객체에 대해서 retain 을 한번 호출한다. 그리고 객체가 포함객체에서 제거될때 release 를 호출해 준다.

13.9.5 규칙5: retain 속성을 갖는 접근자

프로퍼티를 구성할때 @property (retain) ... 과 같이 retain 속성을 지정하면 이 프로퍼티에 객체를 설정하면 retain 메서드를 호출한다.

01: myImage = [[UIImage alloc] init]; // myImage 에 retain –> 1
02: self.userImage = myImage; // myImage 에 retain –> 2
03: [myImage release]; // myImage 에 release –> 1
04: // ...
05: self.userImage = myImage2; // 예전 myImage 에 release -> 0 해제

이와 같이 객체를 설정하는 접근자는 일반적으로 그 객체에 대해서 retain 을 호출한다. 그리고 만약 다른 객체를 재설정하면, 예전 객체에 release 를 호출한다. 위 예제의 3행에서 release 를 호출한 이유를 이해할 것이다.

*규칙5: 메서드가 반환하는 객체는 autorelease

메서드가 객체를 반환한다면 autorelease 된 객체를 반환하는 것이 좋다.

01: -(NSString*) findTopPlayer {
02: NSString *ret = [[top objectAtIndex:0] copy];
03: [ret autorelease];
04: return ret;
05: }

[출처: http://maclove.pe.kr/32]



출처 : http://blog.naver.com/PostView.nhn?blogId=baek2187&logNo=150059860682
Posted by 오늘마감

댓글을 달아 주세요

오브젝트C2010. 6. 22. 09:53
[Objective-C]메모리 관리
메모리는 기본적으로 alloc 메소드로 메모리를 할당하고 init 관련 메소드로 초기화 하여 사용합니다.
이 과정에서 alloc 으로 할당된 메모리를 필요 없는경우 해제해 주어야 원활한 프로그램 운용이 됩니다.

Objective-C에서는 새로운 인스턴스 객체를 만들때 클래스에 alloc이라는 메세지를 보내 인스턴스 객체가 할당될 메모리 영역이 동적으로 확보되고 여기에 인스턴스 변수의 정보가 채워집니다. id 객체 타입은 실제로 이 주소를 가르키는 포인터 입니다.
 
Objective-C에서는 레퍼런스 카운트 방식을 이용합니다. 객체가 생성되거나 참조된다면 카운트를 올려주고 그 반대일 경우에는 카운트를 내려주는데 최종적으로 아무도 참조하고 잇지 않다면 해제하는 방식 입니다.
카운터 값의 변경은 개발자가 해 주어야 합니다. 이 방식은 Objective-C 1.0에서 도입되어 Objective-C 2.0에서도 유지되고 있습니다.
 
이 방식 이외에 Java 에서 전형적인 방식인 가비지 컬렉션 방식이 사용되기도 합니다.
 
* 레퍼런스 카운트가 증가하는 경우
 - Alloc 으로 메모리 할당하였을 경우.
 - retain 했을경우.
 - new 했을 경우
 - copy 했을경우(복사본이 증가, 원본은 변경 없음)
 
* 레퍼런스 카운트가 감소하는 경우
 - release 했을 경우
 
release 메세지는 카운트를 감소하는 경우인데 release 메세지가 실제로 객체를 해제하지는 않습니다. 실제로 객체를 해제하는 메소드는 dealloc 입니다. alloc 은 클래스 메소드지만 dealloc 은 인스턴스 메소드 입니다.
release 의 호출로 인하여 레퍼런스 카운트가 0이 된다면 dealloc이 자동으로 호출 되므로 직접 dealloc을 호출하면 안도비니다.
 
이와 다른 개념으로 AutoreleasePool 이 있습니다. 이는 메모리 자동해제로 AutoreleasePool에 등록하여 해제될 객체들을 이곳에 등록 한 후 AutoreleasePool 이 해제될때 객체들을 한번에 해제하는 것입니다. 여기에 등록된다면 레퍼런스 카운트의 변화도 없고 바로 객체가 해제 되지도 않습니다.
이의 주요한 사용처는 객체가 바로 해제되지 않는다는 점 입니다. 개발자가 직접 alloc 과 init을 하여 객체를 생성 하였다면 개발자가 레퍼런스 카운트를 체크할 수 있겠지만 메소드를 통하여 생성된 객체를 리턴 받은 경우라면 메소드 내에서 레퍼런스 카운트가 얼마나 쌓였을지도 모르기 때문에 이럴때 autorelease 메소드를 호출하여 AutoreleasePool에 등록하여 줍니다.
그리고 AutoreleasePool 이 해제될 때 함께 메모리에서 해제되게 됩니다.
 
AutoreleasePool 이 편리한 기능이기는 하지만 AutoreleasePool이 해제될때 한꺼번에 객체를 처리하기 때문에 많은 양의 메모리가 쌓인다면 시스템에 무리를 줄 수 있습니다.
 


출처 : http://blog.naver.com/PostView.nhn?blogId=khagaa&logNo=30083754415

'오브젝트C' 카테고리의 다른 글

[Objective-C]가비지 컬렉션  (0) 2010.06.22
[Objective-C]카테고리 예제  (0) 2010.06.22
[Objective-C]메모리 관리  (0) 2010.06.22
[Objective-C] 클래스  (0) 2010.06.22
[Objective-C]id 에 관하여  (0) 2010.06.22
[Objective-C] 기본 클래스  (0) 2010.06.22
Posted by 오늘마감

댓글을 달아 주세요

XCODE2010. 6. 21. 18:28
OSX 한글 입력 및 전환 키 관리 프로그램 바람 입력기
한글 입력을 쉽게 도와 주는 바람입력기 입니다.
설치 후  다국어 > 입력메뉴 에서 바람을 체크한 후 재부팅하여 사용하면 됩니다.
 
다운로드:  www.baram.or.kr


출처 : http://blog.naver.com/PostView.nhn?blogId=mewizard&logNo=20065571142
Posted by 오늘마감

댓글을 달아 주세요