-
메모리 동적 할당 및 해제C언어 2020. 3. 4. 19:58
메모리 동적 할당의 필요성
이전 포스트에서 흔히 사용하는 변수는 가상메모리에서 Stack영역의 메모리를 사용하는 것이며 최대 1MB의 크기의 메모리를 사용할 수 있다고 하였다. 그렇다면 프로그램이 더 많은 메모리 자원을 필요로 할 때 or 필요한 메모리의 크기를 확정할 수 없을 때의 경우에는 프로그램이 메모리를 어떻게 할당 받아야 하는가? 라는 의문이 생길 것이다.
예를 들어 학점을 구하는 프로그램이 있을 때 프로그램 제작자는 각 학생들의 점수를 저장해야 할 것이다. 또한 점수를 저장하기 위해서는 메모리의 크기를 기술하여 OS로 부터 메모리 자원을 할당받아야 할 것이다. 이때 학급의 인원이 30명이라고 가정하여 제작자가 int[30] 만큼의 크기의 메모리를 빌려서 프로그램을 작성했다고 했을 때 만약 학급의 인원이 많아진다면 30명을 초과하는 학급 인원의 점수는 저장할 수 없을 것이다. 이런 경우 때문에 메모리 동적 할당이라는 방법을 통해 제작자는 변동하는 학급 인원에 맞추어 메모리를 할당 받을 수 있다.
메모리 동적 할당 이란 ?
메모리 동적 할당이란 위와 같이 메모리 부족, 메모리 크기 기술 시 항상 필요한 메모리가 변동하는 문제등이 생겼을 때 OS 에게 추가적인 메모리의 할당을 요청하는 것이다. 또한 동적 할당을 통해 접근 할 수 있는 메모리는 Heap 영역의 메모리를 의미한다. 추가적으로 메모리를 할당 받았기 때문에 당연히 다시 OS에게 반환 해주어야 할 의무가 있다.
예를 들어 프로그램이 동작 할 때 메모리가 부족 할 때 OS 에게
"나 메모리 부족하니까 Heap 메모리의 x 크기 만큼 접근할 수 있게 허락 해줘"
라고 요청을 하면 OS는 남는 메모리가 있을 경우 해당 프로그램에게 메모리에 접근할 수 있는 key를 준다. 여기서 key는 해당 메모리의 주소이다. 따라서 프로그램은 OS가 승인해준 메모리의 주소로 접근 해 추가적인 메모리를 사용할 수 있게 되는 것이다.
C의 메모리 동적 할당 및 해제
C에서 OS에게 추가적인 메모리 요청 즉 메모리 동적 할당을 위해서는 함수를 이용하게 된다. 이번 포스트에서는 malloc 함수와 free 함수에 대해서 다룰 것이다.
int main(void) { int n = 0, stn = 0, sum = 0; int *pnum = NULL; printf("학생 수 를 입력하세요 : "); scanf_s("%d", &n); pnum = (int *)malloc(sizeof(int) * n); for (int i = 0; i < n; ++i){ printf("학생의 성적을 입력하시오 : "); scanf_s("%d", &stn); *(pnum + i) = stn; printf("학생의 성적 %d가 입력되었 습니다 \n", *(pnum + i)); sum += *(pnum + i); free(pnum); } printf("학생들의 총 성적은 %d 입니다 \n", sum); }
위의 자료는 n의 학급 인원을 받아 n크기의 메모리를 사용 ( 메모리 동적할당 사용 ) 하여 각 인원의 점수를 저장하여 저장된 점수를 모두 더하는 프로그램이다. 위의 프로그램을 통해 메모리 동적 할당 및 해제에 필요한 함수의 사용과 원리에 대해 다룰 것이다.
malloc 함수 (메모리 동적 할당)
위의 구문은 malloc 함수를 통해 OS에게 메모리에 대한 접근을 허용 받기 위한 구문이다. 가장 먼저 pnum 포인터에 OS가 반환하는 주소값을 담는다. 이 때 pnum 포인터 변수에 들어가는 값은 malloc함수의 반환 값이며 이 반환 값은 void * 즉 따로 자료형이 정해지지 않은 주소이다. 따라서 ( int * ) 와 같이 형변환을 통해 int 자료형으로 해당 주소에 있는 메모리의 값을 해석한다고 선언한 상태이다. 마지막으로 malloc 함수의 매개변수는 필요한 메모리의 크기를 기술 한다.
실제로 pnum 포인터에 0x 00539B48이라는 Heap 메모리의 주소가 할당 된 것을 볼 수 있다. 할당 받은 메모리로 접근해보자
성공적으로 int 자료형의 n개 (5 입력) 만큼 할당 받아진다. 즉 이제부터 해당 메모리의 접근 권한을 OS로 부터 획득 하였으며 실질적으로 해당 메모리를 사용할 수 있게 되었다.
free 함수 (메모리 동적 해제)
동적할당 받은 메모리를 다시 OS에게로 반환하는 방법은 간단하다 free 함수를 통해 할당받은 메모리의 주소를 매겨변수로 넘겨주면 반환이 된다. 따라서 free 함수의 매개변수로 pnum 즉 포인터를 넘겨줌으로 써 해당 포인터에 기술 되어있는 malloc 함수의 반환 값인 주소가 매개변수로 넘어가지게 된다.
여기서 한가지 의문이 생간다. 왜 malloc 함수 즉 메모리 동적 할당 과정에서는 할당 받을 메모리의 크기를 기술하였는데 반환 할 때는 할당 받은 메모리의 크기를 기술하지 않는가 이다. 이는 OS가 내부적으로 다음과 같은 과정을 통해 동적 할당으로 빌려준 메모리를 관리하기 때문이다.
메모리 인도를 보면 할당 받은 메모리가 시작하는 점과 끝나는 지점 요소로 부터 int 자료형 1개의 크기 즉 int 요소 하나만큼의 메모리에 fd 라는 값이 들어가있는 것을 볼 수 있다. OS는 내부적으로 위와 같이 할당 해준 메모리의 앞 뒤로 경계선을 지정 한 뒤 해당 경계선에 맞게 다시 메모리를 반환 받기 때문에 메모리 해제시에는 따로 크기를 기술 하지 않아도 된다.
추가적으로 만약 할당 받은 메모리의 크기를 벗어난 메모리에 접근하여 메모리를 사용한다면 위와 같이 경계선을 기준으로 추가적인 메모리의 사용을 인지하고 경고를 띄우게 된다.
만약 프로그램을 작성시 동적 할당받은 메모리를 OS에게 반환하지 않을 경우 해당 메모리는 프로세스가 종료되는 시점에 OS가 강제로 메모리를 회수하게 된다.