C 표준 라이브러리의 메모리 할당 함수인 void *realloc(void *ptr, size_t size)는 malloc 또는 calloc 함수로 이전에 할당된 메모리 블록(ptr이 가리키는 영역)의 크기를 재조정하는 역할을 합니다. 즉, 한 번 할당한 메모리의 크기를 프로그램 실행 중에 유연하게 늘리거나 줄일 수 있도록 도와주는 함수입니다.
C 언어의 메모리 할당 방식
C 언어에서 메모리는 크게 두 가지 방식으로 할당할 수 있습니다.
- 정적(컴파일 시간) 할당: 컴파일 시점에 메모리 크기가 결정됩니다.
- 동적(실행 시간) 할당: 프로그램 실행 중 필요에 따라 메모리를 할당합니다.
컴파일 시점에 메모리가 한 번 할당되면 실행 도중에는 그 크기를 변경할 수 없습니다. 이로 인해 실제 필요한 양보다 메모리가 부족해지거나, 반대로 과도하게 할당되어 낭비되는 문제가 발생할 수 있습니다.
이러한 문제의 해결책은 프로그램 실행 중 사용자의 요구 사항에 맞춰 메모리를 동적으로 생성하는 것입니다.
동적 메모리 관리에 사용되는 C 표준 라이브러리 함수는 다음과 같습니다.
- malloc()
- calloc()
- realloc()
- free()
realloc() 함수의 특징
- 이미 할당된 메모리를 다시 할당(재조정)하는 데 사용됩니다.
- 할당된 메모리 크기를 늘리거나 줄일 수 있습니다.
- 재할당된 메모리의 시작 주소(기본 주소)를 가리키는 void 포인터를 반환합니다.
- 재할당에 실패하면 NULL을 반환하며, 원래 메모리 블록은 그대로 유지됩니다.
realloc() 함수의 문법은 다음과 같습니다.
void *realloc(void *pointer, size_t newsize);
realloc() 기본 사용 예시
다음 예시는 realloc() 함수로 메모리 크기를 줄였다가 다시 늘리는 기본적인 사용 방법을 보여줍니다.
int *ptr; ptr = (int *) malloc(1000); // calloc도 사용 가능 - - - - - - - - - ptr = (int *) realloc(ptr, 500); // 크기 축소 - - - - - - ptr = (int *) realloc(ptr, 1500); // 크기 확장
realloc() 활용 C 프로그램 예제
다음은 calloc()으로 배열을 생성한 뒤, realloc() 함수를 사용해 배열 크기를 동적으로 확장하는 C 프로그램입니다.
#include <stdio.h>
#include <stdlib.h>
int main(){
int *ptr, i, num;
printf("배열 크기는 5입니다\n");
ptr = (int*)calloc(5, sizeof(int));
if(ptr == NULL){
printf("메모리 할당 실패");
exit(1); // 프로그램 종료
}
for(i = 0; i < 5; i++){
printf("%d번째 숫자 입력: ", i);
scanf("%d", ptr+i);
}
printf("\n배열 크기를 7로 늘립니다\n ");
ptr = (int*)realloc(ptr, 7 * sizeof(int));
if(ptr == NULL){
printf("메모리 할당 실패");
exit(1); // 프로그램 종료
}
printf("\n정수 2개를 더 입력하세요\n\n");
for(i = 5; i < 7; i++){
printf("%d번째 요소 입력: ", i);
scanf("%d", ptr+i);
}
printf("\n최종 배열:\n\n");
for(i = 0; i < 7; i++){
printf("%d ", *(ptr+i));
}
return 0;
}
실행 결과
위 프로그램을 실행하면 다음과 같은 결과가 출력됩니다.
배열 크기는 5입니다 0번째 숫자 입력: 23 1번째 숫자 입력: 12 2번째 숫자 입력: 45 3번째 숫자 입력: 67 4번째 숫자 입력: 20 배열 크기를 7로 늘립니다 정수 2개를 더 입력하세요 5번째 요소 입력: 90 6번째 요소 입력: 60 최종 배열: 23 12 45 67 20 90 60
realloc() 사용 시 주의사항
- realloc()이 실패하면 NULL을 반환하지만 기존 메모리는 유지되므로, 반환값을 곧바로 원래 포인터에 대입하기보다는 임시 포인터에 받아 확인하는 것이 안전합니다.
- 첫 번째 인수로 NULL을 전달하면 malloc()과 동일하게 동작합니다.
- 크기를 0으로 지정하면 메모리가 해제될 수 있으며, 이 경우 free()를 사용하는 것이 권장됩니다.
- realloc()으로 확장된 새로운 영역의 초기값은 정의되어 있지 않으므로, 필요하다면 직접 초기화해야 합니다.
- 사용이 끝난 메모리는 반드시 free()로 해제하여 메모리 누수를 방지해야 합니다.