본문 바로가기
#컴퓨터 과학 [Computer Science]/운영체제 (Operating System)

[OS - 🍎 macOS] ARC (Automatic Reference Counting)

by cy_mos 2020. 3. 22.
반응형
카테고리 게시글 작성 날짜 게시글 최근 수정 날짜 작성자
Operating System 2020-03-22 20:37 2022.02.23. 20:47 Dev.Yang

 

[OS - 🍎 macOS] ARC (Automatic Reference Counting)

 

  • Automatic Reference Counting (ARC) 자동적으로 더 이상 필요하지 않은 클래스의 인스턴스를 메모리에서 해제하는 방식으로 동작하는 메모리 관리 기법입니다.
  • Automatic Reference Counting (ARC)은 Objective-C 인스턴스들에 대한 메모리를 자동적으로 관리하여 주는 컴파일러의 기능입니다. 또한, Automatic Reference Counting (ARC)는 애플리케이션의 인스턴스 사이의 관계 그리고 객체 그래프에 대한 코드 작성에 집중할 수 있도록 도와주며 인스턴스에 대한 Retain/Release 연산을 개발자가 더 이상 고려할 필요가 없습니다.

 

  • Automatic Reference Counting (ARC) automatically frees up the memory used by class instances when those instances are no longer needed.
  • Automatic Reference Counting (ARC) is a compiler feature that provides automatic memory management of Objective-C objects. Rather than having to think about retain and release operations, ARC allows you to concentrate on the interesting code, the object graphs, and the relationships between objects in your application.

 

🛠 ARC (Automatic Reference Counting)와 GC (Garbage Collection) 차이점 (Difference between Automatic Reference Counting and Garbage Collection)

메모리 관리 기법 Automatic Reference Counting Garbage Collection
참조 카운팅 시점 컴파일 프로그램 동작 중
장점
  • 컴파일 당시 이미 인스턴스의 해제 시점이 정해져 있어서 인스턴스가 언제 메모리에서 해제될지 예측할 수 있습니다.
  • 컴파일 당시 이미 인스턴스의 해제 시점이 정해져 있어서 메모리 관리를 위한 시스템 자원을 추가할 필요가 없습니다.
  • 상호 참조 상황 등의 복잡한 상황에서도 인스턴스를 해제할 수 있는 가능성이 더 높습니다.
  • 특별히 규칙에 신경을 쓸 필요가 없습니다.
단점
  • ARC의 작동 규칙을 모르고 사용하면 인스턴스가 메모리에서 영원히 해제되지 않을 가능성이 존재합니다.
  • 프로그램 동작 외에 메모리 감시를 위한 추가 자원이 필요하므로 한정적인 자원 환경에서는 성능 저하가 발생할 수 있습니다.
  • 명확한 규칙이 없기 때문에 인스턴스가 정확히 언제 메모리에서 해제될지 예측하기 어렵습니다.
야곰,스위프트 프로그램, 한빛미디어 (2019), p472.

🗂 Automatic Reference Counting (ARC) Works

Automatic Reference Counting (ARC)는 컴파일과 동시에 인스턴스를 메모리에서 해제하는 시점이 결정이 되기 때문에, 개발자가 원하는 방향으로 메모리 관리가 이루어지기 위해서는 Automatic Reference Counting (ARC)에게 명확한 메시지를 전달하여야 합니다.

 

클래스의 인스턴스를 생성할 때마다 Automatic Reference Counting (ARC)는 해당 인스턴스에 대한 정보를 저장하기 위해서 메모리 공간을 따로 할당을 합니다. 그 메모리 공간에는 인스턴스의 타입 정보와 함께 해당 인스턴스와 관련된 저장 프로퍼티의 값을 저장합니다. 그 후에 인스턴스가 더 이상 필요 없는 상태가 되면 인스턴스가 차지하던 메모리 공간을 다른 용도로 활용할 수 있도록 Automatic Reference Counting (ARC)가 메모리에서 인스턴스를 할당 해제합니다.

 

개발자의 실수로 아직 더 사용해야 하는 인스턴스를 메모리에서 해제시킨다면 인스턴스와 관련된 프로퍼티에 접근하거나 인스턴스의 메서드를 호출할 수 없으며 이를 무시하고 강제로 인스턴스에 접근하려고 할 경우에는 잘못된 메모리 접근으로 인하여 프로그램이 강제 종료될 수 있습니다.

 

이처럼 인스턴스가 지속해서 필요한 상황에서는 Automatic Reference Counting (ARC)는 인스턴스가 메모리 상에서 해제되지 않도록 인스턴스에 대한 참조 여부를 계속해서 추적합니다. 다른 인스턴스의 프로퍼티나 변수, 상수 등 어느 한 곳에서 인스턴스를 참조한다면 Automatic Reference Counting (ARC)가 해당 인스턴스를 해제하지 않고 유지해야 한다는 명분이 됩니다.

 

이렇듯 인스턴스를 메모리에 유지시키려면 이러한 명분을 꼭 명심하여야 합니다. 왜냐하면, 잘못된 규칙으로 인하여 강한 참조 순환 문제 (Strong Reference Cycle)이 발생할 수 있기 때문입니다.


🗂 Using Automatic Reference Counting (ARC) Objective-C

[영문]

  • Programs cannot call the functions NSAllocateObject and NSDeallocateObject
  • Programs cannot use object pointers in C structures (struct)
  • Programs cannot use memory zones (NSZone)
  • To properly cooperate with non-acode, programs must use no method or declared property (unless explicitly choosing a different getter) that starts with new.

[국문]

  • NSAllocateObject and NSDeallocateObject 함수들을 호출할 수 없습니다.
  • C언어 구조체 타입 내부에 객체 포인터를 사용할 수 없습니다.
  • 메모리 구역 (NSZone)을 사용할 수 없습니다.
  • ARC를 적용하지 않는 코드를 적절하게 사용하기 위해서는, 반드시 new keyword를 시작하는 메소드 또는 선언된 프로퍼티를 사용하지 않아야 합니다.

+ Using Automatic Reference Counting (ARC) Objective-C Source Code

더보기
// Without ARC
- (void)dealloc
{
   [[NSNotificationCenter defaultCenter] removeObserver:self];
   [super dealloc];
}
 
// With ARC
- (void)dealloc
{
   [[NSNotificationCenter defaultCenter] removeObserver:self];
   // [super dealloc] is called automatically
}

 

[영문]

retainreleaseretainCountautorelease or dealloc cannot be sent to objects. Instead, the compiler inserts these messages at compile time automatically, including [super dealloc] when dealloc is overridden.

 

[국문]

retainreleaseretainCountautorelease 또는 dealloc에 대한 메세지를 객체에 보낼 수 없습니다. 대신에, 컴파일러는 dealloc이 오버라이드 (Overridden) 되었을 때 [super dealloc] 포함하여 컴파일 시간 때 이러한 메시지를 자동적으로 삽입합니다.


// Without ARC
- (NSString *)giveMeAString
{
    CFStringRef myString = [self someMethodThatCreatesACFString];
    NSString *newString = (NSString *)myString;
    return [newString autorelease];
}
 
// With ARC
- (NSString *)giveMeAString
{
    CFStringRef myString = [self someMethodThatCreatesACFString]; // retain count is 1
    NSString *newString = (__bridge_transfer NSString *)myString; // the ownership has now been transferred into ARC
    return newString;
}

 

[영문]

Programs cannot cast directly between id and void *. This includes casting between Foundation objects and Core Foundation objects. Programs must use special casts, or calls to special functions, to tell the compiler more information about an object's lifetime.

 

[국문]

id 그리고 void * 사이에 직접적으로 캐스트를 수행할 수 없습니다. 또한 여기에는 Foundation Objects 그리고 Core Foundation Objects 간의 캐스트를 포함합니다. Object's 수명주기에 관한 더 많은 정보를 컴파일러에게 알려주기 위해서 반드시 특별한 캐스트 또는 특별한 함수들을 사용하여야 합니다.


// Without ARC
- (void)loopThroughArray:(NSArray *)array
{
    for (id object in array) {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        // Create a lot of temporary objects
        [pool drain];
    }
}
 
// With ARC
- (void)loopThroughArray:(NSArray *)array
{
    for (id object in array) {
        @autoreleasepool {
            // Create a lot of temporary objects
        }
    }
}

 

[영문]

An autorelease pool can be used to allocate objects temporarily and retain them in memory until the pool is "drained". Without ARC, an NSAutoreleasePool object can be created for this purpose. ARC uses @autoreleasepool blocks instead, which encapsulate the allocation of the temporary objects and deallocates them when the end of the block is reached.

 

[국문]

autorelease pool은 pool이 "drained" 될 때까지 메모리 내에 Objects를 일시적으로 할당하거나 유지하는 데 사용합니다. 이처럼 Automatic Reference Counting (ARC)를 사용하지 않는 경우에, NSAutoreleasePool 생성하여 Objects 메모리를 관리하는 목적으로 사용되고 있습니다. 또한, Automatic Reference Counting (ARC) 사용하는 경우에는 @autoreleasepool 사용하는 대신에, 일시적으로 할당된 Objects를 캡슐화를 수행하고 코드 블록의 끝에 도달하였을 경우에 할당 해제 작업을 수행합니다. 

+ Using Automatic Reference Counting (ARC) Swift Code

더보기
var myString: String                   // Can only be a string
var myOtherString: String?             // Can be a string or nil
 
if let myString = myOtherString {      // Unwrap the Optional
    print(myString)                    // Print the string, if present
}

 

[영문]

In Swift, references to objects are strong, unless they are declared weak or unowned. Swift requires explicit handling of nil with the Optional type: a value type that can either have a value or be nil. An Optional type must be handled by "unwrapping" it with a conditional statement, allowing safe usage of the value, if present. Conversely, any non-Optional type will always have a value and cannot be nil.

 

[국문]

Swift에서는 weak 또는 unowned로 선언하지 않는 한, 기본적으로 strong 선언됩니다. Swift는 옵셔널 타입의 값 타입은 값을 가지고 있는지 또는 nil인지를 명확하게 처리과정이 필요합니다. Optional Type이 값을 가지고 있는 경우에는 반드시 "unwrapping" 조건 구문을 사용하여 안전하게 값을 사용할 수 있도록 처리되어야 합니다. 그에 반대로, non-Optional type은 항상 값이 존재하며 nil이 아니여야 합니다.


var strongReference: MyClass          // Strong reference, cannot be nil
weak var weakReference: MyClass?      // Weak reference, can be nil
unowned var unownedReference: MyClass // Weak reference, cannot be nil

 

[영문]

Accordingly, a strong reference to an object cannot be of type Optional, as the object will be kept in the heap until the reference itself is deallocated. A weak reference is of type Optional, as the object can be deallocated and the reference be set to nil. Unowned references fall in-between; they are neither strong nor of type Optional. Instead, the compiler assumes that the object to which an unowned reference points is not deallocated as long the reference itself remains allocated. This is typically used in situations where the target object itself holds a reference to the object that holds the unowned reference.

 

[국문]

게다가, 강한 참조 (Strong Reference) 객체는 옵셔널 타입으로서 지정할 수 없으며, 강한 참조의 객체가 할당 해제가 될 때까지 힙 메모리 영역에 유지됩니다. 약한 참조 (Weak Reference)의 객체는 옵셔널 타입으로 지정할 수 있으며, 약한 참조 객체에 nil을 할당하게 되면 메모리 상에서 할당해제가 됩니다. 미소유 참조 (Unowned Reference)는 강한참조(Strong Reference)와 약한참조 (Weak Reference) 사이에 있습니다. 대신에, 컴파일러는 미소유 참조 (Unowned Reference) 객체가 메모리 상에서 유지될 수 있도록 할당 해제를 하지 않도록 가정합니다. 일반적으로 대상 객체 자체가 미소유 참조를 보유한 객체에 대한 참조를 보유한 상황에서 사용합니다.

 

[영문]

Swift also differs from Objective-C in its usage and encouragement of value types instead of reference types. Most types in the Swift standard library are value types and they are copied by value, whereas classes and closures are reference types and passed by reference. Because value types are copied when passed around, they are deallocated automatically with the reference that created them.

 

[국문]

Swift는 Objective-C와 다르게 참조 타입 대신에  값 타입을 사용을 권장하고 있습니다. Swift Standard Library의 대부분의 자료형들은 값 복사를 수행하는 값 타입입니다. 반면에 클래스 또는 클로저는 참조를 전달하는 참조 타입입니다. 값 타입은 값을 복사하여 전달할 때, 값 복사 시 생성 한 참조 주소를 자동적으로 할당 해제합니다.


🗂 Automatic Reference Counting (ARC) 주의사항

[영문]

Apple Inc. deploys ARC in their operating systems, such as macOS (OS X) and iOS. Limited support (ARCLite) has been available since Mac OS X Snow Leopard and iOS 4, with complete support following in Mac OS X Lion and iOS 5. Garbage collection was declared deprecated in OS X Mountain Lion, in favor of ARC, and removed from the Objective-C runtime library in macOS Sierra.

 

[국문]

Automatic Reference Counting (ARC)은 macOS (OS X) 그리고 iOS 운영체제 환경에서 적용되었습니다. 제한적인 기능을 제공하는 ARCLite는 Mac OS X Snow Leopard 그리고 iOS 4에서 이용 가능하며, Mac OS X Lion 그리고 iOS 5 이상부터는 Automatic Reference Counting (ARC)의 모든 기능을 이용할 수 있습니다. 또한, Automatic Reference Counting (ARC)를 지원하기 위하여 가비지 컬렉션은 OS X Mountain Lion부터 사라지게 되었으며 macOS Sierra 내부의 Objective-C 런타임 라이브러리로부터 제거되었습니다.


🚀 REFERENCE

더보기
반응형

댓글