티스토리 뷰

예전 책에서는 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 이렇게 되어 있는 부분이 @autoreleasepool로 변경이 되어서 찾아보던중의 정리된 내용들이다.


xcode의 버전이 올라가면서, NSAutoreleasePool이 못쓰게 되었다. 실제로는 옵션에서 설정하게 되면 사용을 할수는 있지만, 다른것으로 대체가 되었다. 처음에 이거 왜 이래 이러다가, 한참 헤매였는데... 대충 바꿔서 쓰면 잘된다. 단순하게 코드수를 줄이려고 그런것인지 알수가 없는 노릇이다.


Objective-C가 제공하는 메모리 관리 방식은 3가지가 있다. (더 있다면 누가 말씀 좀...)

  • MRR(Manual retain-release)
    개발자에 의해서 의도적으로 관리되는 방식. retain count로 관리가 된다.
  • ARC(Automatic Reference Count)
    MRR과 같은 참조 수 계산 방식을 사용하지만 컴파일 시 적절한 메모리 관리 함수 호출문을 넣어 처리한다.
  • GC(Garbage Collection)
    더 이상 참조되지 않는 객체를 자동으로 제거하는 방식으로 MMR, ARC와는 많이 다른 메커니즘을 제공함. 일단은 폰류에서는 사용할수 없음. Mac OS X에서만 쓸 수 있다라고 한다.

일단 AutoreleasePool이라는 기법에 대해서 말을 하자면, 연기된 release 메시지를 보내는 메커니즘이다. 즉 객체를 지금 즉시 해제하지 않고, 모아두었다가, release 메시지를 보내기를 원할 때 사용하는 방식이다. (예를 들면 메소드를 통해 생성된 객체가 이런 경우에 속하게 된다.)


사용법은 다음과 같다.

- (NSObject*) initObject
{
    // 이런식이면 대략난감.
    return [NSObject new];
}
- (NSObject*) initObject
{
    // 이렇게 변경
    return [[NSObject new] autorelease];
}

NSAutoreleasePool과 @autoreleasepool에 대하여. 표면적으로 보면 둘은 같아 보인다.
  • NSAutoreleasePool

AutoreleasePool은 NSAutoreleasePool의 인스턴스로 autolease메시지를 받은 객체들이 모이는 풀이다. 이 곳에 모인 객체들은 오토릴리즈 풀이 메모리에서 해제될 때 release 메시지를 받게 된다. 오토릴리즈 풀은 다른 오토릴리즈풀을 담을 수 있는 것처럼 보이는데, 실질적으로 이들은 스택처럼 동작을 한다. 만약 새로운 오토릴리즈 풀을 생성한다면 이는 기존 오토릴리즈 풀 내에 포함되는것이 아니라 오토필리즈 풀 스택의 맨 위에 추가된다. 만약 어떤 객체가 autorelease 메시지를 받는다면, 이 객체는 최상위의 오토릴리즈 풀에 들어가게 된다.


Cocoa는 기본적으로 하나의 오토릴리즈 풀이 사용될 수 있다고 가정한다. 흠... 만약 사용 가능한 오토릴리즈 풀이 없다면 오토릴리즈 객체는 release 메시지를 보내면 Cocoa는 에러를 띄운다. 앱킷이나 UI킷 프레임워크는 각각의 이벤트 루프의 시작점에서 자동적으로 풀을 생성한다. 하지만 다음의 경우에는 별도의 오토릴리즈 풀을 만들어야 한다.

    1. 명령줄 프로그램과 같이 UI킷 혹은 앱킷을 사용하지 않는 프로그램을 만들 때, 앱킷을 사용하지 않는 파운데이션 기반 프로그램의 템플릿은 main함수에서 오토릴리즈 구문을 명시해주고 있다.
    2. 많은 양의 임시 객체를 사용하는 루프를 사용할 경우, 만약 루프안에서 임시 객체를 만들어 쓸 때 루프속에서 오토릴리즈 풀을 만들면 이는 루프를 돌면서 사용하는 메모리의 최대치를 낮게 제어할 수 있다.
    3. 다른 스레드를 만들 때, 오토릴리즈 풀을 생성한다. 스레드가 실행되면 가능한 먼저 오토스레드풀을 만들어야 한다. 그렇지 않으면 메모리가 누수될수가 있다.
NSAutoreleasePool 객체를 만들 때는 [[NSAutoreleasePool alloc] init](혹은 new)통해 생성하고 폐기시에는 drain(혹은 release) 메시지를 보낸다. 오토릴리즈 풀에 autorelease나 retain을 할 경우에는 예외가 발생한다. 오토릴리즈 풀은 생성된 루프나 함수 내에서 폐기되어야 한다. 또한 객체의 인스턴스 변수에 대해서는 오토릴리즈 풀을 생성할 필요도 없고 보통 하지 않는다.

* NSAutoreleasePool의 drain과 release 메소드의 차이
가비지 컬렉터 환경이 지원되느냐 안되느냐의 차이에 따라 약간 다르다. iOS의 경우 GC가 되지 않으니, 두개의 역할은 같다. 그러나 GC가 되는 상황에서는 Pool내의 모든 객체를 release하되, 시스템에서 필요로 하면 Pool 자신을 수거하라고 메시지를 보내게 된다.
  • @autoreleasepool
NSAutoreleasePool객체를 직접 생성하지 않고 @autoreleasepool 블럭을 이용하여 동일한 방식의 코딩이 가능하게 되었다. 아직까지는 편한거 이외에는 차이점을 모르겠음. 일단 ARC개념이 생기면서 NSAutoreleasePool을 대체하기 위해서 나온 키워드 정도...


표면적으로는 같고, 원래 있던 위치에 변경만 하여주면된다.

차이점이 없구만 멀...

NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    // Code
[pool release];
@autoreleasepool
{
    // Code
}


* 주의

풀에 등록된 객체들은 오토릴리즈 풀을 해제하기 전까지는 계속 메모리를 차지하고 있을 것인데 이는 지나친 오버헤드가 될 가능성이 있다. (GC System에서는 알아서 drain/release해준다.)

너무 남발해서 사용할 경우에, 릭이 발생할수 있다는 것이다.

이런 경우에 대해서, 각각의 구간의 autorelease를 만들어서 사용을 하게 되면 된다.



Non-ARC에서는 autorelease pool에 등록되었다가 pool이 없어지면서 해제되고, ARC에서는 __autoreleasing pointer가 아니므로 strong pointer lifecycle에 의해 해제된다.



무슨소리인지... zzz


'Mobile > iOS' 카테고리의 다른 글

[iOS]xcode 콘솔창 따로 띄우기  (2) 2015.02.09
[iOS]Navigation만들기  (0) 2014.12.15
NSData를 파일로 저장, 가져오기  (0) 2014.03.06
NSMutableArray Sort  (0) 2014.03.05
@selector  (0) 2014.03.05
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함