Obj-C 메모리 관리
메모리 관리는 모든 프로그래밍 언어에서 가장 중요한 프로세스 중 하나입니다. 객체의 메모리가 필요할 때 할당되고 더 이상 필요하지 않을 때 할당이 해제되는 프로세스입니다.
개체 메모리 관리는 성능의 문제입니다. 애플리케이션이 불필요한 개체를 해제하지 않으면 메모리 공간이 증가하고 성능이 저하됩니다.
Objective-C 메모리 관리 기술은 크게 두 가지 유형으로 분류 할 수 있습니다.
- "수동 유지 해제"또는 MRR
- "자동 참조 계수"또는 ARC
"수동 유지 해제"또는 MRR
MRR에서 우리는 자체적으로 객체를 추적하여 메모리를 명시 적으로 관리합니다. 이것은 Foundation 클래스 NSObject가 런타임 환경과 함께 제공하는 참조 카운팅이라는 모델을 사용하여 구현됩니다.
MRR과 ARC의 유일한 차이점은 전자에서는 유지 및 해제가 수동으로 처리되고 후자는 자동으로 처리된다는 것입니다.
다음 그림은 Objective-C에서 메모리 관리가 작동하는 방식의 예를 나타냅니다.
Class A 객체의 메모리 수명주기는 위 그림과 같습니다. 보시다시피 유지 횟수는 개체 아래에 표시되며 개체의 유지 횟수가 0이되면 개체가 완전히 해제되고 다른 개체가 사용할 수 있도록 해당 메모리가 할당 해제됩니다.
Class A 객체는 NSObject에서 사용할 수있는 alloc / init 메소드를 사용하여 먼저 생성됩니다. 이제 보유 횟수는 1이됩니다.
이제 클래스 B는 클래스 A의 개체를 유지하고 클래스 A의 개체의 유지 수는 2가됩니다.
그런 다음 클래스 C는 개체의 복사본을 만듭니다. 이제 인스턴스 변수에 대해 동일한 값을 가진 클래스 A의 다른 인스턴스로 생성됩니다. 여기에서 보유 횟수는 1이며 원래 개체의 보유 횟수가 아닙니다. 이것은 그림에서 점선으로 표시됩니다.
복사 된 객체는 release 메서드를 사용하여 Class C에 의해 해제되고 보유 횟수가 0이되므로 객체가 파괴됩니다.
초기 Class A Object의 경우 보유 횟수는 2이며, 폐기하려면 두 번 해제해야합니다. 이는 보유 수를 각각 1과 0으로 감소시키는 클래스 A 및 클래스 B의 릴리스 문에 의해 수행됩니다. 마지막으로 객체가 파괴됩니다.
MRR 기본 규칙
우리가 만든 모든 객체를 소유합니다. 이름이 "alloc", "new", "copy"또는 "mutableCopy"로 시작하는 메서드를 사용하여 객체를 만듭니다.
보유를 사용하여 객체의 소유권을 얻을 수 있습니다. 수신 된 객체는 일반적으로 수신 된 메소드 내에서 유효 함을 보장하며 해당 메소드는 객체를 호출자에게 안전하게 반환 할 수도 있습니다. 두 가지 상황에서 리 테인을 사용합니다.
접근 자 메서드 또는 init 메서드의 구현에서 속성 값으로 저장하려는 개체의 소유권을 가져옵니다.
다른 작업의 부작용으로 객체가 무효화되는 것을 방지합니다.
더 이상 필요하지 않으면 우리가 소유 한 객체의 소유권을 포기해야합니다. 릴리즈 메시지 또는 자동 릴리즈 메시지를 보내 객체의 소유권을 포기합니다. 따라서 Cocoa 용어에서 객체의 소유권을 포기하는 것은 일반적으로 객체를 "해제"라고합니다.
소유하지 않은 객체의 소유권을 포기해서는 안됩니다. 이것은 명시 적으로 언급 된 이전 정책 규칙의 결과 일뿐입니다.
#import <Foundation/Foundation.h>
@interface SampleClass:NSObject
- (void)sampleMethod;
@end
@implementation SampleClass
- (void)sampleMethod {
NSLog(@"Hello, World! \n");
}
- (void)dealloc {
NSLog(@"Object deallocated");
[super dealloc];
}
@end
int main() {
/* my first program in Objective-C */
SampleClass *sampleClass = [[SampleClass alloc]init];
[sampleClass sampleMethod];
NSLog(@"Retain Count after initial allocation: %d",
[sampleClass retainCount]);
[sampleClass retain];
NSLog(@"Retain Count after retain: %d", [sampleClass retainCount]);
[sampleClass release];
NSLog(@"Retain Count after release: %d", [sampleClass retainCount]);
[sampleClass release];
NSLog(@"SampleClass dealloc will be called before this");
// Should set the object to nil
sampleClass = nil;
return 0;
}
위의 프로그램을 컴파일하면 다음과 같은 출력이 나옵니다.
2013-09-28 04:39:52.310 demo[8385] Hello, World!
2013-09-28 04:39:52.311 demo[8385] Retain Count after initial allocation: 1
2013-09-28 04:39:52.311 demo[8385] Retain Count after retain: 2
2013-09-28 04:39:52.311 demo[8385] Retain Count after release: 1
2013-09-28 04:39:52.311 demo[8385] Object deallocated
2013-09-28 04:39:52.311 demo[8385] SampleClass dealloc will be called before this
"자동 참조 계수"또는 ARC
자동 참조 계산 또는 ARC에서 시스템은 MRR과 동일한 참조 계산 시스템을 사용하지만 컴파일 타임에 적절한 메모리 관리 방법 호출을 삽입합니다. 새 프로젝트에 ARC를 사용하는 것이 좋습니다. ARC를 사용하는 경우 일부 상황에서는 유용 할 수 있지만 일반적으로이 문서에 설명 된 기본 구현을 이해할 필요가 없습니다. ARC에 대한 자세한 내용은 ARC 릴리스 노트로 전환을 참조하십시오 .
위에서 언급했듯이 ARC에서는 컴파일러에 의해 처리되므로 릴리스를 추가하고 메서드를 유지할 필요가 없습니다. 실제로 Objective-C의 기본 프로세스는 여전히 동일합니다. 내부적으로 유지 및 해제 작업을 사용하므로 개발자가 이러한 작업에 대해 걱정하지 않고 쉽게 코딩 할 수 있으므로 작성되는 코드의 양과 메모리 누수 가능성이 모두 줄어 듭니다.
MRR과 함께 Mac OS-X에서 사용되는 가비지 컬렉션이라는 또 다른 원칙이 있었지만 OS-X Mountain Lion에서 폐기 된 이후 MRR과 함께 논의되지 않았습니다. 또한 iOS 개체에는 가비지 수집 기능이 없었습니다. 그리고 ARC를 사용하면 OS-X에서도 가비지 콜렉션을 사용하지 않습니다.
다음은 간단한 ARC 예입니다. ARC를 지원하지 않기 때문에 온라인 컴파일러에서는 작동하지 않습니다.
#import <Foundation/Foundation.h>
@interface SampleClass:NSObject
- (void)sampleMethod;
@end
@implementation SampleClass
- (void)sampleMethod {
NSLog(@"Hello, World! \n");
}
- (void)dealloc {
NSLog(@"Object deallocated");
}
@end
int main() {
/* my first program in Objective-C */
@autoreleasepool {
SampleClass *sampleClass = [[SampleClass alloc]init];
[sampleClass sampleMethod];
sampleClass = nil;
}
return 0;
}
위의 프로그램을 컴파일하면 다음과 같은 출력이 나옵니다.
2013-09-28 04:45:47.310 demo[8385] Hello, World!
2013-09-28 04:45:47.311 demo[8385] Object deallocated