숏컷 코드
동적 메모리는 문법보다 수명과 소유권으로 읽는 편이 맞습니다. 런타임 크기, 함수 경계, 해제 책임이 동시에 나오면 malloc과 free를 바로 떠올리면 됩니다.
int n = 10;
int *arr = malloc(sizeof(int) * n);
if (arr == NULL) {
return 1;
}
free(arr);
arr = NULL;문법
자동 변수는 블록을 벗어나면 사라집니다. 반대로 동적 메모리는 malloc으로 직접 얻고, free하기 전까지 살아 있습니다. 그래서 입력에 따라 크기가 바뀌거나, 함수가 끝난 뒤에도 데이터가 남아야 하면 힙을 봅니다.
int n = 5;
int *scores = malloc(sizeof(*scores) * n);
if (scores == NULL) {
return 1;
}
for (int i = 0; i < n; i++) {
scores[i] = i * 10;
}여기서 핵심은 할당 자체보다 누가 이 메모리를 끝까지 관리하는지입니다.
malloc은 메모리만 빌려 주고 초기화는 하지 않습니다. 할당 직후 바로 읽는 대상이 아니라, 먼저 값을 채워야 하는 대상이라고 읽는 편이 안전합니다.
소유권
free는 동적 메모리의 수명을 끝내는 호출입니다. malloc/calloc/realloc이 준 포인터만 해제할 수 있고, 해제 뒤에는 그 주소를 더 이상 믿으면 안 됩니다.
int *buf = malloc(sizeof(*buf) * 4);
if (buf == NULL) {
return 1;
}
free(buf);
buf = NULL;오류 경로에서 free를 빠뜨리면 누수가 생기고, 해제 후 포인터를 계속 쓰면 use-after-free가 됩니다. C 메모리 버그의 상당수가 여기서 시작합니다.
- 런타임 크기나 긴 수명이 필요하면 동적 메모리를 본다.
malloc은 초기화하지 않으므로 먼저 값을 채운다.free는 정확히 한 번만, 올바른 포인터에만 호출한다.- 해제 책임이 누구에게 있는지 함수 계약에서 분명해야 한다.
- 해제 직후
ptr = NULL은 후속 실수를 줄이는 데 도움이 된다.
주의할 점
해제한 메모리를 다시 읽거나 쓰면 use-after-free가 됩니다. C에서는 이 버그가 조용히 데이터를 망가뜨리다 뒤늦게 터지기 쉽습니다.
int *p = malloc(sizeof(int));
free(p);
// ❌ 더 이상 유효하지 않음
*p = 99;해제 직후 NULL을 대입하는 습관은 이런 실수를 줄이는 데 도움이 됩니다.
참고 링크
2 sources