가비지 컬렉터 [ 크래프톤 정글 45일차 ]

jinsung·2025년 6월 28일

크래프톤 정글 9기

목록 보기
43/59

지금까지 메모리 관리에 대해 여러가지 포스팅을 작성하면서

메모리를 malloc 이나 mmap 시스템 콜을 써서 할당하고
free를 사용해서 꼭 해제해 줘야 한다는 것을 배웠습니다.

C언어를 사용할 때에는 더 이상 필요하지 않는 메모리를 free해주는 것은 우리의 책무예요.
안해주면 진짜 서운함.

사실 서운한 건 아니고, 에러입니다. 할당한 블록을 회수해주지 않는건 에러예요.

이 코드를 한번 볼까요?

void garbage()
{
	int *p = (int *)Malloc(15213);
    
    return; /* 엥 님아 왜 반환해요. */
}

포인터 변수 pmalloc으로 할당해줬는데 free로 메모리 해제를 안해줬어요..

까먹었습니다... 예.. 프로그래머가 까먹었어요...

가비지컬렉터는 무료로 free를 호출해 줍니다.

1. 가비지 컬렉터

가비지 컬렉터는 더 이상 프로그램에서 사용하지 않는 블록들은 자동으로 반환해줘요.
사용하지 않는 블록들을 가비지(쓰레기)라고 해요.

가비지 컬렉터가 이런 쓰이지 않는 블록들을 주기적으로 확인해서 주기적으로 free를 실행해줘요.

2. Mark & Sweep 알고리즘

가비지 컬렉션을 수행하는 방식도 여러가지가 있긴한데
오늘은 책에 적혀있고 가장 기본적인 방식인 Mark & Sweep 알고리즘 방식에 대해서 작성하겠습니다.

Mark & Sweep 알고리즘은 딱 두 가지 단계로 이루어져 있어요.

  • Mark 단계
  • Sweep 단계

그 과정이 어떻게 이루어지는지 살펴볼게요.

2-1. Mark 단계

먼저, 프로그램이 사용 중인 메모리 블록들을 표시합니다. 이를 Marking 이라고 해요.

  1. 스택,전역변수,레지스터 등에 들어있는 포인터들부터 시작
  2. 그 포인터들이 가리키는 블록들을 따라감
  3. 블록 안에 또 다른 포인터가 있다면 계속 따라감
  4. 행님 이거 살아있습니다. 하고 표시해줌

이 과정이 끝나면 살아있는 블록에는 표시가 되어있을거고, 쓰이지 않는 블록들은 표시가 없게 될거예요.

왜냐하면

힙 영역에 있는 블록들을 스택,전역변수,레지스터에 있는 애들로만 따라갔잖아요
저기서 갈 수 없는 애들은 연결이 안되서 Marking이 안되어있는거임!!

2-2. Sweep 단계

살아있는 ( 연결이 되는 ) 블록들은 Marking 단계에서 표시가 되어있으니까
표시가 없는 블록들을 free로 해제해주면 되는거예요!!

if (block is marked)
    unmark it; // 다음 GC를 위해 표시를 지움
else if (block is allocated)
    free(block); // 가비지니까 회수!

oh my god , it's so easy

가비지 컬렉터 짱짱맨이죠? 근데.....

3. C에서의 Mark & Sweep 방식의 보수적인 접근

Mark & Sweep 방식은 가비지 컬렉팅하는 C를 위한 적절한 방법인데
왜냐하면 위 방식이 블록을 이동시키지 않은 채로 동작하기 때문이예요.

그런데 여기서 중요한 문제가 하나 있어요.

❗ C 언어는 변수 타입을 런타임에 모릅니다.

어떤 값이

  • 진짜 포인터인지,
  • 그냥 우연히 포인터처럼 생긴 int 값인지

컴파일 타임에는 알 수 있지만 런타임에는 모릅니다.

그래서 가비지 컬렉터는 isPtr(p)라는 함수로 p가 진짜 포인터인지, 어떤 블록을 가리키는지 찾아야 하는데,

이게 C에서는 걍 킹받는 일입니다.

0x0000001111이 정수 15인지 포인터인지 어케알아요 ㅠ

그래서 어떻게 하냐면?

그냥 보수적 판단해요.

조금이라도 포인터일 수 있는 값은 다 포인터라고 생각해서 보수적으로 처리합니다.

진짜로 사용 중인 블록은 놓치면 안 되니까,

안 쓰는 블록을 가끔 못 지우더라도 괜찮다는 식으로 동작해요.

그래서 이런 방식을 Conservative GC (보수적인 가비지 컬렉터) 라고 부릅니다.

4. 하지만 완벽하진 않다

Conservative GC는 안정적이긴 하지만, 단점도 있어요.

  • 진짜 포인터가 아닌 값을 포인터로 착각하면?
    → 가비지가 회수되지 않음 → 메모리 낭비
  • 그럼에도 프로그램의 정확성은 보장됨
    → 너무 조심해서 잘못된 메모리 회수는 안 함

이게 바로 C 언어에 딱 맞는 절충안입니다.

마무리

제가 프론트엔드로 일 할 때도 , 자바스크립트의 가비지 컬렉션이 단골 CS 면접 질문이었는데요.

이렇게 정글에와서 정확히 알게되니까 기분이가 좋크든요~ > <

1개의 댓글

comment-user-thumbnail
2025년 6월 28일

말록 쓰고 프리하는 걸 잊지말록....

답글 달기