Computer >> 컴퓨터 >  >> 프로그래밍 >> C 프로그래밍

C 언어 동적 메모리 할당 완벽 정리: malloc부터 free까지 예제로 배우기

문제

C 프로그래밍에서 동적 메모리 할당(Dynamic Memory Allocation)을 활용하여 사용자가 입력한 n개의 숫자를 저장하고, 그 합계를 구하는 프로그램을 작성해 보겠습니다.

해결 방법

동적 메모리 할당은 C 프로그래머가 프로그램 실행 중(런타임)에 필요한 만큼 메모리를 유연하게 확보할 수 있도록 해주는 강력한 기능입니다. 배열처럼 컴파일 시점에 크기를 고정하지 않기 때문에, 필요한 만큼만 메모리를 사용하여 낭비를 줄일 수 있습니다.

런타임에 메모리를 동적으로 할당할 때 사용되는 대표적인 함수는 다음과 같습니다.

  • malloc() — 런타임에 지정한 바이트 크기만큼의 메모리 블록 하나를 할당합니다.
  • calloc() — 런타임에 연속된 여러 개의 메모리 블록을 할당하며, 초기값이 0으로 설정됩니다.
  • realloc() — 이미 할당된 메모리의 크기를 줄이거나 늘릴 때 사용합니다.
  • free() — 더 이상 필요하지 않은, 이전에 할당된 메모리 공간을 해제합니다.

아래의 C 프로그램은 사용자로부터 요소의 개수를 입력받고, 각 요소를 저장한 뒤 전체 합계를 계산하여 출력합니다. 동적 메모리 할당 함수를 활용함으로써 고정 크기 배열에서 발생할 수 있는 메모리 낭비를 효과적으로 줄일 수 있습니다.

핵심 포인트

  • malloc() 호출 후 반환값이 NULL인지 반드시 확인하여 메모리 할당 성공 여부를 검사해야 합니다.
  • 포인터 산술(p + i)을 이용해 할당된 메모리에 접근할 수 있습니다.
  • 프로그램 종료 전 free()로 메모리를 해제하면 메모리 누수를 방지할 수 있습니다.

예제 코드

#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 value)이 출력됨 //
    }
}

실행 결과

Enter the number of elements : 5
Enter the elements :
23
34
12
34
56
The sum of elements is 159
Displaying the cleared out memory location :
12522624
0
12517712
0
56

결과 분석

위 실행 결과에서 알 수 있듯이, free() 함수로 메모리를 해제한 후 해당 메모리 위치를 다시 출력하면 의미 없는 쓰레기 값(garbage value)이 표시됩니다. 이는 해제된 메모리 공간이 운영체제나 다른 프로세스에 반환되었음을 보여주는 것으로, 동적 메모리의 생명주기를 이해하는 데 중요한 부분입니다. 따라서 실무에서는 free() 호출 후 해당 포인터를 더 이상 참조하지 않도록 주의해야 하며, 안전을 위해 포인터에 NULL을 대입하는 것이 좋은 습관입니다.