동적 메모리 할당 (malloc, calloc, realloc, free)


정적 vs 동적 할당

 정적 할당동적 할당
영역스택
크기고정 (컴파일 타임)유동 (런타임)
관리자동 해제free() 직접 호출
크기 한계작음 (MB)큼 (GB도 가능)
사용 예int arr[10]malloc(n * sizeof(int))

함수별 정리

함수별비교

malloc — 기본 할당

void* malloc(size_t size);
  • 지정한 바이트만큼 힙에 할당
  • 초기화 없음 → 쓰레기값(garbage) 주의
  • 실패 시 NULL 반환
int* arr = (int*)malloc(5 * sizeof(int));
if (!arr) return -1;  // NULL 체크 필수

calloc — 0 초기화 할당

void* calloc(size_t n, size_t size);
  • n개 요소 × size 바이트 할당
  • 전체를 0으로 초기화 → 배열에 적합
  • 실패 시 NULL 반환
int* arr = (int*)calloc(5, sizeof(int));  // 모두 0

malloc보다 약간 느리지만, 초기화 누락 버그를 원천 차단


realloc — 크기 변경

void* realloc(void* ptr, size_t new_size);
  • 기존 할당 블록의 크기를 확장하거나 축소
  • 뒤에 공간 있으면 제자리 확장 (주소 그대로)
  • 뒤에 공간 없으면 새 위치로 이동 후 데이터 복사 → 기존 블록 자동 해제
  • 새로 늘어난 부분은 초기화 안 됨
  • 실패 시 NULL 반환 (기존 포인터는 유효한 상태로 유지)
// 잘못된 방법 — 실패시 ptr이 NULL이 되어 기존 메모리 누수
ptr = realloc(ptr, new_size);

// 올바른 방법
int* tmp = realloc(ptr, new_size);
if (tmp) ptr = tmp;

REALLOC 내부동작

내부동작


free — 메모리 해제

void free(void* ptr);
  • 동적 할당된 메모리 반납. 사용 후 반드시 호출
  • 해제 후 포인터를 NULL로 초기화하는 습관 권장
free(ptr);
ptr = NULL;  // 댕글링 포인터 방지

free 하면 안 되는 경우

잘못된 예이유
스택 변수에 free(&x)동적 할당된 메모리만 해제 가능
같은 포인터 두 번 freeDouble free → 힙 손상
free 후 포인터 재사용댕글링 포인터 → Undefined Behavior
free 없이 종료메모리 누수

한눈에 비교

함수초기화주요 용도
malloc없음빠르게 할당만 필요할 때
calloc0으로 초기화배열 등 초기화가 중요할 때
realloc새 영역 없음크기를 동적으로 바꿔야 할 때
free사용 후 반드시 호출

안전한 패턴

안전한패턴


체크리스트

  • malloc / calloc 반환값 NULL 체크
  • 동적 할당 사용 후 free() 호출
  • realloc은 반환값을 임시 변수에 먼저 받기
  • free() 후 포인터에 NULL 대입
  • 스택 변수에 free() 하지 않기

© 2022 JeongHwan Yun.