자료구조 연결 리스트를 공부하던 중 malloc함수가 튀어 나왔는데 이해하지 못해 잠깐 멈추고 malloc함수에 대해 정리를 하고 출발하려고 한다.
malloc함수는 메모리의 동적할당을 위해서 사용하는 것이라고 한다. 그렇다면 동적할당이 무엇인가? 부터 시작을 해보자.
1. 동적메모리할당(Dynamic Memory Allocation)
동적 메모리 할당 또는 메모리 동적 할당은 컴퓨터 프로그래밍에서 실행 시간 동안 사용할 메모리 공간을 할당하는 것을 말한다. 사용이 끝나면 운영체제가 쓸 수 있도록 반납하고 다음에 요구가 오면 재 할당을 받을 수 있다. 이것은 프로그램이 실행하는 순간 프로그램이 사용할 메모리 크기를 고려하여 메모리의 할당이 이루어지는 정적 메모리 할당과 대조적이다.
동적으로 할당된 메모리 공간은 프로그래머가 명시적으로 해제하거나 쓰레기 수집이 일어나기 전까지 그대로 유지된다. C/C++와 같이 쓰레기 수집이 없는 언어의 경우, 동적 할당하면 사용자가 해제하기 전까지는 메모리 공간이 계속 유지된다. 동적 할당은 프로세스의 힙영역에서 할당하므로 프로세스가 종료되면 운영 체제에 메모리 리소스가 반납되므로 해제된다. 그러나 프로세스가 계속 실행될 때에는 동적할당 된 영역은 유지되므로 프로그램이 정해진 힙 영역의 크기를 넘는 메모리 할당을 요구하면 할당되지 않는다. 따라서 사용이 완료된 영역은 반납하는 것이 유리한데, 프로그래머가 함수를 사용해서 해제해야 한다.
동적 할당은 함수가 종료되거나 변수 영역을 벗어나면 자동으로 공간 해제가 이루어지는 스택을 사용한 자동 변수와 대조적이다. 프로세스의 정적 메모리 할당은 프로세스가 시작할 때 이미 정해진 메모리량으로 한정되어있기 때문에, 프로세스가 시작할 때부터 끝날 때까지 유지되는데 반해, 동적 할당은 프로세스의 실행 과정 중에 필요한 메모리를 운영체제에 요구해 할당받고 해제하는 것이 가능하다.
출처: 위키백과
데이터 영역과 스택 영역에 할당되는 메모리의 크기는 컴파일 타임(compile time)에 미리 결정됩니다.
하지만 힙 영역의 크기는 프로그램이 실행되는 도중인 런 타임(run time)에 사용자가 직접 결정하게 됩니다.
이렇게 런 타임에 메모리를 할당받는 것을 메모리의 동적 할당(dynamic allocation)이라고 합니다.
출처: TCP SCHOOL
그러니까 동적할당은 프로그램이 시작될때 할당되는 것이 아닌 프로그램이 실행되는 도중에 메모리 공간(heap 영역)에 할당되는 것을 의미한다.
이와 관련된 함수들은 stdilb.h라는 헤더 파일 안에 포함되어 있기 때문에 시작할때 전처리 지시자 #include 를 사용해서 헤더파일을 추가해줘야 한다.
#include <stdilb.h>
그럼 stdilb.h파일 내부에 있는 동적할당을 위한 함수들을 확인해보자.
malloc 함수
- malloc() 함수의 원형
void * malloc ( size_t size ); -> size 바이트의 메모리를 힙에서 할당하여 반환한다.
malloc()함수는 인수로 할당받고자 하는 메모리의 크기를 바이트 단위로 전달받는다.
malloc()함수는 전달받은 메모리 크기에 맞고, 아직 할당되지 않은 적당한 블록을 찾는다.
이렇게 찾은 블록의 첫 번째 바이트를 가리키는 주소값을 반환한다.
malloc()함수는 메모리만 할당하는 함수이기에 어떤 데이터를 사용하는지 알수 없다. 그렇기에
void포인터를 반환하고서 사용자가 원하는대로 변환해서 사용할수 있게 설계 되었기에 원형은
void으로 되어 있는 것이다. 원하는 자료형으로 캐스팅(형변환)해서 사용하면 되는데
그냥 void 자리에 원하는 자료형으로 작성해서 사용하면 자동으로 캐스팅 되어 사용된다.
(int*)malloc(~~~); 과같이..
#size_t는 부호없는 정수 자료형을 의미하고 sizeof연산자, offsetof메크로의 결과를 말한다.
(int*)malloc(sizeof(int));
malloc()함수 내부에 인수는 바이트 단위로 작성만 하면 되기에 계산 수식을 넣어주기도 한다
(int*)malloc(sizeof(int)*4);
보통의 사용법은
(데이터타입 * )malloc(sizeof(데이터타입)*할당크기); 와 같은 방식으로 사용한다.
free 함수
Java의 경우는 메모리 동적 할당된 공간이 더이상 참조하지 않는다면 알아서 가비지 컬렉터가 메모리 공간을 해제하지만 C언어의 경우는 동적으로 할당한 메모리 공간을 직접 해제 해주지 않으면 메모리 누수가 발생할수 있다.
그러기 위해 동적으로 할당한 공간을 해제해주는 함수인 free() 함수가 필요하다
- free() 함수의 원형
void free(void * ptr) - ptr이 가르키는 메모리를 해제한다.
free() 함수는 인수로 해제하고자 하는 메모리 공간을 가리키는 포인터를 전달받는다.
인수 타입이 void형 포인터로 선언되어 있기에 어떤 타입의 포인터라도 인수로 전달 될수 있다.
보통 사용법은
free(동적 할당된 포인터 변수);
ex)
int* malVal = (int*)malloc(sizeof(int));
free(malVal);
과 같이 사용한다.
동적 할당하는 메서드는 malloc()외에도 colloc(), realloc()이 있으나 이는 추후에 포스팅에 추가 하겠다.
글이 잘 정리되어 있네요. 감사합니다.