C언어에서는 "가비지 컬렉터"가 없기에 프로그래머가 직접 메모리 관리를 해주어야 합니다. 즉, 프로그래머가 데이터를 저장할 메모리 공간을 적절히 나누는 "메모리 할당" 작업을 진행해야 하는 것입니다. C언어에서의 메모리 할당 방법은 "정적 메모리 할당"과 "동적 메모리 할당" 이렇게 두 가지가 있습니다. 지금부터 C언어에서의 메모리 할당 방법에 대해서 알아보도록 하겠습니다.
메모리 구조
컴퓨터 운영체제는 여러 가지 정보나 사용자가 입력한 데이터를 기억하기 위한 메모리 공간을 제공하는데, 대표적인 메모리 공간으로는 "코드 영역(Code Segment)", "데이터 영역(Data Segment)", "스택 영역(Stack Segment)", "힙 영역(Heap Segment)"가 있습니다.
- 코드 영역 (Code Segment): 컴파일러가 C언어 소스를 기계어로 바꾸어 실행 프로그램을 만들고 실행 파일을 실행합니다. 프로그램 자체의 영역이며, 소스 코드로부터 번역된 기계어 명령들이 코드 영역에 복사되어 프로그램을 실행하는데 사용됩니다.
- 데이터 영역 (Data Segment): 프로그램이 시작해서 끝날 때까지 사용되는 데이터들이 이 공간에 저장됩니다. 즉, 프로그램에 사용되는 전역 변수와 정적 변수들이 저장되는 공간입니다.
- 스택 영역 (Stack Segment): 스택 영역은 함수의 호출과 관련된 지역 변수와 매개변수들이 저장되는 공간입니다. 함수의 호출과 함께 할당되며 함수의 종료와 함께 소멸됩니다. 이렇게 스택 영역에 저장되는 함수의 호출 정보를 "스택 프레임"이라고 합니다.
- 힙 영역 (Heap Segment): 힙 영역은 밑에서 살펴볼 "동적 메모리 할당"을 통하여 만들어진 "동적 변수"를 저장하기 위한 빈 공간입니다.
정적 메모리 할당
컴파일러가 코드를 기계어로 번역하는 시점에 변수를 저장할 메모리 위치를 배치하는 것이 "정적 메모리 할당"입니다. 스택에 할당되어 있는 메모리이며, 프로그램을 실행할 때 메모리의 크기가 확정되어 있기에 프로그램이 실행되는 도중에는 크기를 변경할 수 없습니다.
정적 메모리의 가장 큰 장점은 "메모리가 누수될 것을 걱정할 필요가 없다는 것"입니다. 프로그램이 실행될 때 이미 메모리 크기가 정해지며, 프로그램이 종료되면 운영체제가 자동으로 메모리 공간을 회수해갑니다.
반면, 정적 메모리의 단점은 아까 말했듯, "메모리가 낭비될 수 있다는 것"입니다. 예를 들어 처음에는 대략 100만큼의 메모리 공간을 사용할 것 같아 100만큼의 메모리를 받아놓았는데, 실제로는 10만큼의 메모리만 사용했다면 나머지 90만큼의 메모리는 낭비되는 것입니다. 이것은 정적 메모리 할당에서는 프로그램이 실행될 때 메모리 크기가 정해져 있기에, 프로그램이 실행 중일 경우 크기를 변경할 수 없기에 그렇습니다.
동적 메모리 할당
"동적 메모리 할당"이란 프로그래머가 원하는 시점에 자신이 원하는 만큼의 메모리 크기를 할당하고 해제하는 방식을 말합니다. 즉, 정적 메모리 할당과는 달리 "프로그램이 실행되는 도중에 메모리를 할당받는 것"이 가능한 메모리 할당 방법입니다. 동적 메모리 할당은 malloc 함수를 통하여 메모리 할당을 진행할 수 있습니다.
사용자가 size 변수에 지정한 크기만큼 힙 영역에 메모리를 할당하고, 그 할당한 주소 형식을 void * 형식으로 반환하는 방식으로 사용합니다.
// C언어에서 malloc 함수를 통해 메모리 동적 할당하기
void *malloc(size_t size) // 함수 원형이며, 이때 size_t는 int와 같은 자료형을 말합니다.
void *p = malloc(100) // 100바이트 메모리를 포인터 p에 동적 할당합니다.
// 아래와 같은 방식으로 동적 메모리 할당을 많이 사용합니다.
arr = (int*)malloc(sizeof(int) * 4); // size 4 동적할당
이렇게 동적으로 메모리를 할당한 후에는 "반드시" 메모리를 해제해야 합니다. 정적 메모리 할당에서는 운영체제가 자동으로 메모리를 해제해주지만, C언어의 동적 메모리 할당 방식에서는 프로그래머가 free 함수를 통해 힙에 할당한 메모를 해제해주어야 합니다.
// C언어에서 동적으로 할당한 메모리를 free함수를 통해 해제하기
free(ptr); // ptr이 가지고 있는 주소에 할당된 메모리를 해제합니다.
그리고 malloc 함수와 free 함수를 사용하기 위해서는 #include <stdlib.h> 전처리기를 코드 상단에 추가해야 합니다.