C 언어로 프로그래밍을 하려면 메모리에 대한 이해가 매우 중요합니다. 하지만 초보자에게 메모리 개념은 다소 추상적으로 느껴질 수 있는데요. 이 글에서는 가상 메모리, 스택과 힙, 동적 메모리 할당, 그리고 흔히 하는 메모리 관리 실수와 그 해결 방법을 쉽게 설명해보겠습니다. 이론보다는 직접 실습해볼 수 있는 예제 코드를 중심으로 다루겠습니다.
이미지 출처: KwonKusang
가상 메모리란?
컴퓨터에서 프로그램이 사용하는 메모리는 실제 물리적 메모리(RAM)와 1대1로 대응되지 않습니다. 가상 메모리(Virtual Memory)란 운영체제가 제공하는 기능으로, 프로그램마다 독립적인 메모리 공간을 갖는 것처럼 보이게 하는 기술입니다. 마치 각 프로그램이 자신만의 큰 마을이나 별도의 집합 공간을 부여받는 것과 비슷합니다. 이 가상 주소 공간 덕분에 하나의 프로그램이 다른 프로그램의 메모리에 침범하지 않으며, 프로그램은 매우 큰 연속된 메모리를 가진 것처럼 작업할 수 있습니다.
예를 들어, 우리가 C 프로그램에서 어떤 변수의 주소(&변수
)를 출력해보면 항상 큰 값의 메모리 주소가 나오는데, 이 주소는 가상 주소입니다. 운영체제는 이 가상 주소를 실제 물리 메모리 주소로 변환하여 사용합니다. 초보 단계에서는 가상 메모리의 내부 작동 원리를 깊게 알 필요는 없지만, 각 프로그램이 서로 독립된 메모리 공간을 가진다는 점과, C에서 보이는 메모리 주소들은 가상화된 주소라는 정도만 알아두면 됩니다.
메모리 구조: 스택과 힙
C 프로그램이 실행될 때 메모리 공간은 용도에 따라 몇 가지 영역으로 나뉩니다. 그 중 스택(Stack)과 힙(Heap)은 특히 중요합니다.
-
스택(Stack): 스택은 함수 호출과 지역 변수를 위해 사용되는 메모리 공간입니다. 새로운 함수가 호출될 때마다 스택에 변수들이 쌓이고(LIFO, Last-In First-Out 구조), 함수가 종료되면 쌓았던 메모리를 자동으로 치웁니다. 예를 들어 함수 안에서 변수를 선언하면 그 변수가 스택에 저장되고, 함수가 끝날 때 자동으로 제거됩니다. 스택 영역의 특징은 자동 할당/해제라는 점입니다. 프로그래머가 직접 관리하지 않아도 함수 호출과 함께 할당되고 반환 시 자동으로 해제되므로 편리하지만, 크기가 한정되어 있어 너무 많은 데이터를 담으면 스택 오버플로우가 발생할 수 있습니다.
-
힙(Heap) 구역: 힙은 동적 메모리 할당을 위해 사용되는 메모리 공간입니다. 힙은 스택과 달리 개발자가 직접 관리하는 영역입니다. 힙 영역은 스택보다 훨씬 크고 보다 자유롭게 활용 가능합니다. 단, 자유로운 대신 사용한 사람이 정리까지 책임져야 합니다. C에서는
malloc
,calloc
,realloc
등을 사용해 힙에 메모리를 할당하고, 사용이 끝난 메모리는 반드시free
함수로 해제해야 합니다. 힙에 할당한 메모리는 프로그래머가free
를 호출하기 전까지 유지되며, 함수를 빠져나가도 남아있습니다. 따라서 힙은 유연성이 높지만, 잘못 관리하면 메모리 누수 등의 문제가 생길 수 있습니다.
요약하면, 스택은 지역 변수와 함수 호출에 쓰이는 자동 관리 메모리이고, 힙은 필요에 따라 할당/해제하는 수동 관리 메모리입니다. 스택은 쌓았다가 자동으로 치우는 접시 더미 같고, 힙은 필요할 때 직접 꺼내쓰고 되돌려줘야 하는 창고 같은 곳이라고 할 수 있겠습니다.
스택과 힙 메모리 사용 예시
스택과 힙의 차이를 코드로 한 번 확인해보겠습니다. 아래 간단한 코드에서는 스택에 할당된 변수와 힙에 할당된 변수를 만들어보고, 그 주소를 출력해봅니다.