C 표준 라이브러리의 메모리 할당 함수 void *malloc(size_t size)는 요청한 크기만큼의 메모리를 할당하고, 그 메모리의 시작 주소를 가리키는 포인터를 반환합니다.
메모리 할당 방식
C 언어에서 메모리는 크게 두 가지 방식으로 할당할 수 있습니다.
- 정적 할당(Static Allocation) – 컴파일 시점에 메모리 크기가 결정됩니다.
- 동적 할당(Dynamic Allocation) – 프로그램 실행 중 필요한 만큼 메모리를 확보합니다.
컴파일 시점에 메모리가 한 번 할당되면 실행 도중에는 크기를 변경할 수 없습니다. 이 경우 실제 필요량보다 메모리가 부족하거나, 반대로 과다하게 선언해 낭비가 발생하는 문제가 생깁니다.
이러한 문제의 해결책이 바로 동적 메모리 할당입니다. 프로그램 실행 중 사용자의 요구 사항에 맞춰 필요한 만큼 메모리를 생성하는 방식입니다.
동적 메모리 관리 표준 라이브러리 함수
- malloc()
- calloc()
- realloc()
- free()
malloc() 함수란?
malloc() 함수는 런타임에 바이트 단위로 메모리 블록을 할당하는 데 사용됩니다. 반환값은 void 포인터이며, 할당된 메모리 영역의 시작 주소(베이스 주소)를 가리킵니다.
malloc()의 기본 문법은 다음과 같습니다.
void *malloc (바이트 단위 크기)
예제 1
다음은 malloc() 함수의 기본적인 사용 방법을 보여주는 예입니다.
int *ptr; ptr = (int *) malloc(1000); // int형 n개 크기만큼 할당하는 더 안전한 방법 int *ptr; ptr = (int *) malloc(n * sizeof(int));
참고: 할당 가능한 여유 메모리가 없으면 malloc()은 NULL을 반환합니다. 따라서 반환값을 반드시 확인해야 합니다.
예제 프로그램
아래는 동적 메모리 할당 함수 malloc()의 동작을 보여주는 C 프로그램입니다.
#include<stdio.h>
#include<stdlib.h>
void main(){
// 변수와 포인터 선언 //
int numofele,i;
int *p;
// 배열 원소 개수 입력 받기 //
printf("Enter the number of elements in the array: ");
scanf("%d",&numofele);
// malloc 함수로 메모리 할당 //
p = (int *)malloc(numofele * (sizeof(int)));
// 포인터 배열에 값 저장 및 출력 //
for(i=0;i<numofele;i++){
p[i]=i+1;
printf("Element %d of array is : %d\n",i,p[i]);
}
}실행 결과
Enter the number of elements in the array: 4 Element 0 of array is : 1 Element 1 of array is : 2 Element 2 of array is : 3 Element 3 of array is : 4
예제 2
다음은 동적 메모리 할당 함수를 활용해 원소를 입력받고 합계를 구한 뒤, free()로 해제된 메모리 상태를 확인하는 C 프로그램입니다.
#include<stdio.h>
#include<stdlib.h>
void main(){
// 변수, 포인터, 합계 변수 선언 //
int numofe,i,sum=0;
int *p;
// 원소 개수 입력 받기 //
printf("Enter the number of elements : ");
scanf("%d",&numofe);
// malloc() 함수 호출 //
p=(int *)malloc(numofe*sizeof(int));
/* 메모리가 성공적으로 할당되었는지
반드시 if문으로 검사해야 한다 */
if (p==NULL){
printf("Memory not available");
exit(0);
}
// 원소 입력 및 합계 계산 //
printf("Enter the elements : \n");
for(i=0;i<numofe;i++){
scanf("%d",p+i);
sum=sum+*(p+i);
}
printf("\nThe sum of elements is %d",sum);
free(p); // 할당된 메모리 해제 //
printf("\nDisplaying the cleared out memory location : \n");
for(i=0;i<numofe;i++){
printf("%d\n",p[i]); // 쓰레기(garbage) 값이 출력됨 //
}
}실행 결과
Enter the number of elements : 5 Enter the elements : 12 10 24 45 67 The sum of elements is 158 Displaying the cleared out memory location : 7804032 0 7799120 0 67
위 결과에서 볼 수 있듯이, free()로 메모리를 해제한 후 해당 위치를 다시 읽으면 의미 없는 쓰레기 값이 출력됩니다. 이는 해제된 메모리를 더 이상 신뢰할 수 없음을 보여주는 좋은 예이며, 동적 메모리 사용 후에는 반드시 free()로 해제하고 해제된 포인터에는 접근하지 않아야 함을 시사합니다.