가비지 컬렉터(Garbage Collection)
C++에서는 메모리를 프로그래머가 관리한다. 즉, 동적 할당된 메모리를 전부 사용했다면 시스템에 돌려줘야 한다.
하지만, 프로그래머도 사람이기에 실수가 일어나는데 일어나는 실수는 다음과 같다.
1. 메모리 누수
메모리 사용이 끝났음에도 메모리를 해제하지 않은 경우
2. 이중 해제
메모리를 이미 해제 했는데 다시 해제하는 경우
(이미 해제된 메모리를 가리키는 포인터를 댕글리 포인터라고 한다.)
3. 해제 실수
아직 사용중인 메모리를 해제하는 경우
이런 불편함을 해결하기 위해 나온 기술이 자동으로 메모리를 관리하는 가비지 컬렉션(Garbage Collection)이다.
가비지 컬렉션을 지원하는 언어를 매니지드 언어(Managed Language)라고 한다.
동작 원리
가비지 컬렉션은 가비지 컬렉터(Gabage Collector)가 더이상 사용하지 않는 메모리(Gabage)를 재사용함으로써 동작된다.
하지만 아쉽게도 어떤 객체가 아직 사용되고 있고, 사용되지 않는지 정확하게 판별할 수 있는 알고리즘은 없다.
그래서 다음과 같은 2가지 방법으로 객체의 사용유무를 판단한다.
1. 추적 가비지 컬렉션(Tracing Garbage Collection)
- 추적 방식에서는 도달 가능성(Reachability)으로 생존을 가정하는데 루트(Root)를 사용해 해당 메모리까지 도달 할 수 있는지를 시도하고, 도달되지 못한 메모리는 가비지로 가정한다.

2. 참조 카운팅(Reference Couting)
참조 카운팅 방식에서는 해당 메모리에 참조하는 것이 아무것도 없으면 가비지로 가정한다.
참조 카운팅 방법에서 순환 참조(Circular Reference)를 주의해야 하는데, 이를 방지하기 위해 약한 참조(Week Reference)라는 개념을 사용한다. 이 두 방법은 하이브리드 형식으로 같이 사용될 수 있다.
순환 참조(Circular Reference) : 서로 다른 두 메모리가 서로를 참조하는 것
약한 참조(Week Reference) : 가비지 판단 기준인 참조 횟수에는 영향을 주지 않고 참조를 하는 것

가비지 컬렉션의 종류는 보수적 가비지 컬렉션(Conservative Garbage Collection), 복제 가비지 컬렉션(Copying Garbage Collection), 분산 가비지 컬렉션(Disributed Garbage Collection), 증분 가비지 컬렉션(Incremental Garbage Collection) 등등 여러가지가 있다.
C# 에서의 가비지 컬렉션
C#에서도 가비지 컬렉션을 지원하는데 C#에서 사용하는 방식은 세대별 가비지 수집(Generational Garbage Collection)이다.
세대별 가비지 수집
세대별 가비지 수집을 얘기하기 전에 먼저 세대(Generation)에 대한 이해가 필요하다.
가비지 컬렉터가 관리하는 메모리를 매니지드 힙(Managed Heap)이라고 하는데, 이 힙을 0세대, 1세대 및 2세대의 총 3개 세대로 나눠 관리한다.
매니지드 힙에는 여러 개의 포인터가 있으며 이를 이용해 세대를 구별한다.

세대를 나눈 이유는 메모리를 재사용하기 용이하기 때문이다.
여기서 메로리 재사용이 용이한 이유는?
1. 가비지 컬렉션이 일어날 때 파편화를 방지하기 위해 메모리를 압축하는 데, 당연한 소리지만 힙 전체를 대상으로 하는 것 보다 일부분에서만 수행 하는 게 더 빠르다.
2. 최근에 만들어진 객체일 수록 수명이 짧고 오래 사용된 객체일 수록 수명이 길어 재사용할 메모리를 빠르게 분류할 수 있다.
3. 메모리 할당은 0세대에서만 일어나는데 최근에 만들어진 객체끼리 서로 연관되는 경향이 있어 캐싱 측면에서 좋다.
메모리 할당
C#에서 모든 참조 타입의 객체는 매니지드 힙의 0세대에 할당되고 각 객체들은 주소 공간이 허락하는 한 인접한 곳에 위치하게 된다.
매니지드 힙은 메모리를 미리 시스템으로부터 할당 받아 놓기 때문에(풀링과 비슷하다.) 스택에서 메모리를 할당하는 속도만큼 빠르게 할당할 수 있고, 접근도 빠르게 할 수 있다.
단, 85KB 이상의 크기를 가지는 큰 객체는 LOH(Large Object Heap)라는 2세대 메모리에 할당된다.
'코딩 > C#' 카테고리의 다른 글
[C#] 대리자 (0) | 2022.08.10 |
---|---|
[C#] Stream (0) | 2022.08.10 |