C# 가비지 컬렉터 (Garbage Collector)

차차·2021년 12월 3일
0

C#

목록 보기
13/14

Garbage Collector

간단히 말하자면, 가비지 컬렉터는 프로그램과 어떠한 연결 고리를 가지고 있지 않은 쓸모 없는 객체를 찾아 메모리를 해제하는 것. 즉 쓸모 없는 메모리는 회수 하겠다는 의미이다.

스택과 힙

윈도우 프로그램은 기본적으로 하나의 스레드를 갖는다. 그리고 개별 스레드마다 전용으로 사용할 수 있는 저장소가 메모리에 할당되는데 그 영역을 스택이라고 한다.
반면 은 프로그램에서 필요에 의해 메모리를 사용하겠다고 요청했을 때 사용할 수 있는 저장소다. 특별히 닷넷에서는 CLR이 직접 프로그램에서 사용될 힙을 관리한다. 일반적으로 메모리를 사용한 후에는 그것을 해제할 수도 있어야 한다. 할당만 하고 해제를 하지 않으면 유한한 자원인 메모리는 일정 시간 후에는 더는 사용할 영역이 남아있지 않아 프로그램의 실행 과정에 오류가 발생한다.
여기서 스택은 변수를 선언하는 것 만으로 스택내의 특정 메모리 영역을 사용할 수 있게 자동화 된다. 따라서 스택에 대한 메모리 할당/ 해제에 관해서는 개발자가 걱정할 필요가 없다. 하지만
힙에 메모리를 할당하는 것은 해제하는 과정이 필요하고 해제의 과정은 c# 프로그램 관리 환경 내의 특정 구성요소인 Garbage Collector 가 담당하게 된다.

시점?

C#프로그램에서 모든 참조형 변수를 생성할 때는 GC가 관여하게 되고, 이는 요청된 변수의 타입이 요구하는 메로리를 "관리 힙" 이라는 곳에 할당한다. 또한 프로그램이 실행되고 있는 중에 GC는 스스로 적절하다고 판단되는 시점이 되면 관리 힙을 청소하는 작업을 하는데, 이때 어떤 객체가 더는 사용되고 있지 않는다면 객체의 데이터를 해제해 버린다. 따라서 C# 의 참조형 변수가 가리키는 객체는 GC가 호출되어야 소멸자가 호출된다.

즉 불확실한 시점에 메모리를 정리 한다는 사실...

C#프로그램에서 new 로 할당되는 모든 참조형 객체는 힙에 할당된다. 물론 메모리는 무한대로 쓸 수 있는 자원이 아니다. 따라서 일정 수준의 메모리 할당이 발생하면 GC가 동작된다. GC는 힙에 있는 객체 중에서 현재 사용되지 않는 객체는 제거해 버림으로써 여유 공간을 확보한다. 아쉽게도 GC의 동적은 프로그램의 다른 동작을 중지시킨다는 것을 염두에 둬야 한다. 즉 힙을 많이 사용할수록 GC는 더 자주 동작하고 그만큼 프로그램은 빈번하게 실행이 중지되어 심각한 성능 문제를 겪을 수 있다.

가비지 컬렉터

CLR의 힙은 세대(generation) 으로 나뉘어 관리된다. 처음 new로 할당된 객체는 0세대 (generation 0) 에 속한다. 이는 GC타입을 이요해 코드로도 알아 낼 수 있다.

static void Main(string[] args)
{
	Program pg = new Program();
    Console.WriteLine(GC.GetGeneration(pg))); // 출력 결과 : 0 
}

처음 할당되는 객체는 모두 0세대에 속한다. 0세대 객체의 총 용량이 일정 크기를 넘어가면 GC는 가비지 수집을 한다. 사용되지 않는 0세대 객체가 있으면 없애고, 그 시점에도 사용되고 있는 객체는 1세대(generation 1) 로 승격된다. 프로그램이 실행되면서 이런 가비지 수집 작업은 반복되고 1세대로 승격된 객체의 총 용량도 일정 크기를 넘어가게 된다. 그럼 GC는 0세대와 1세대에 모두 가비지 수집을 한다. 1세대의 객체가 그 시점에도 사용되고 있으면 2세대(generation 2) 로 승격한다. 프로그램이 실행되면서 역시 2세대로 승격된 객체의 총 용량도 일정 크기를 넘어가게 된다. 그럼 GC 는 0세대 부터 2세대에 걸쳐 모든 객체를 가비지 수집한다.
하지만 이번에는 2세대의 객체가 계속 사용된다고 해서 3세대로 승격되는 것은 아니다. CLR의 세대는 2세대가 끝이다. 이후 2세대의 메모리 공간은 시스템이 허용하는 한 계속 커지게 된다.

profile
개발하는 돌멩이🙄🙄👻

0개의 댓글