
C언어 malloc free를 배우기 시작하면 많은 사람이 “할당은 알겠는데 왜 해제가 이렇게 무서울까?”라는 느낌을 받습니다. 이유는 malloc 자체보다, 메모리를 언제 해제하고 그 뒤 포인터를 어떻게 다뤄야 하는지가 더 어렵기 때문입니다.
이번 글에서는 malloc/free를 단순 함수 사용법으로 끝내지 않고, dangling pointer, memory leak, double free가 왜 위험한지를 메모리 수명 관점에서 정리하겠습니다.

malloc과 free를 가장 짧게 설명하면
malloc은 프로그램 실행 중 필요한 만큼 메모리를 빌리는 함수이고, free는 그 메모리를 다 쓴 뒤 다시 반납하는 함수입니다. 즉 자동으로 정리되지 않는 메모리를 개발자가 직접 관리하는 구조라고 보면 됩니다.
int *arr = (int *)malloc(sizeof(int) * 3);
if (arr == NULL) return 1;
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
free(arr);
arr = NULL;C 포인터 설명을 같이 보면, 포인터가 단순 변수보다 메모리 수명과 더 강하게 연결된 개념이라는 점이 보입니다. malloc/free를 이해할 때도 이 수명 관점이 핵심입니다.
이 예시에서 핵심은 할당보다 해제 이후입니다. free를 했다고 해서 포인터 변수 자체가 자동으로 NULL이 되지는 않습니다. 그래서 해제한 뒤에도 예전 주소를 들고 있는 포인터가 남을 수 있습니다.
dangling pointer가 왜 위험할까
dangling pointer는 더 이상 유효하지 않은 메모리를 계속 가리키는 포인터입니다. 이미 free된 메모리를 계속 참조하거나, 수명이 끝난 지역 변수 주소를 들고 있는 경우가 대표적입니다.
문제는 이 포인터가 겉으로는 여전히 “주소 같은 값”을 들고 있어서, 초보자 눈에는 멀쩡해 보인다는 점입니다. 하지만 그 주소는 더 이상 안전하게 사용할 수 없습니다.
memory leak와 double free는 어떻게 다를까
- memory leak: 빌린 메모리를 반납하지 않아 점점 쌓이는 문제
- double free: 이미 반납한 메모리를 또 반납하려는 문제
- dangling pointer: 이미 끝난 메모리를 계속 가리키는 문제
셋은 비슷해 보여도 각각 위험이 다릅니다. leak는 메모리를 잃어버리는 문제이고, double free와 dangling pointer는 프로그램 안정성을 직접 깨뜨릴 수 있습니다.
입문자가 자주 하는 실수
- malloc 결과를 NULL 체크하지 않는다
- free한 뒤에도 같은 포인터를 계속 쓴다
- 한 메모리를 두 포인터가 같이 들고 있는데 한쪽만 생각한다
- 해제 후 NULL 대입을 하지 않아 실수를 빨리 못 잡는다
특히 free 후 NULL 대입은 모든 문제를 막아주지는 않지만, 적어도 같은 포인터를 실수로 다시 쓰는 일을 줄이는 데 도움이 됩니다.
포인터 기본 감각은 포인터 입문 글과 이어지고, 그 다음 단계로는 이중 포인터 글과도 자연스럽게 연결됩니다.

마무리
C언어 malloc/free의 핵심은 함수를 외우는 것이 아니라, 메모리를 언제 빌리고 언제 반납하며 그 뒤 포인터 상태가 어떻게 변하는지 이해하는 데 있습니다.
즉 동적 메모리에서 가장 중요한 질문은 “지금 이 포인터가 아직 유효한 대상을 가리키고 있는가”입니다. 이 질문을 놓치지 않는 습관이 메모리 버그를 크게 줄입니다.