앞 글에서 malloc은 대부분 빠르지만,
특정 순간에는 느려질 수 있다고 정리했다.
그런데 실제로 메모리 관련해서 더 자주 마주치는 문제는 따로 있다.
free를 했는데 메모리 사용량이 그대로다
처음 보면 꽤 당황스럽다.
free(p);
코드상으로는 분명히 메모리를 해제했다.
그런데 top이나 htop 같은 걸 보면 RSS가 그대로다.
이건 버그가 아니라,
메모리가 그렇게 동작하도록 설계되어 있기 때문이다.
free는 “메모리 반환”이 아니다
여기서 한 번 개념을 다시 잡고 가야 한다.
우리가 흔히 생각하는 건 이거다.
malloc → OS에서 가져옴
free → OS에 돌려줌
하지만 실제로는 다르다.
free는 OS에 메모리를 돌려주는 게 아니라,
malloc에게 “이거 다시 써도 된다”고 알려주는 동작이다
즉, 내부에서는 이렇게 된다.
malloc → 메모리 사용
free → allocator 내부로 반환
OS 입장에서는 아무 일도 안 일어난다.
그래서 RSS는 그대로다
여기서 RSS를 보면 이해가 된다.
RSS = 실제 물리 메모리에 올라와 있는 양
free 이후 상태를 보면 이렇다.
- 메모리는 사용 안 함
- 하지만 프로세스에 그대로 붙어 있음
- 물리 메모리에도 그대로 존재
즉,
“안 쓰고 있지만, 들고는 있는 상태”
라서 RSS가 줄어들지 않는다.
그럼 왜 바로 OS에 안 돌려줄까
이건 성능 때문에 그렇다.
만약 free가 항상 OS에 반환한다면
malloc → system call
free → system call
이렇게 된다.
문제는 명확하다.
- 시스템 콜 비용 큼
- 커널 진입 발생
- 성능 크게 저하
그래서 allocator는 이렇게 선택한다.
“일단 들고 있다가, 나중에 재사용하자”
이게 바로 메모리 풀 전략이다.
실제로는 대부분 재사용된다
이 구조 덕분에 이런 일이 가능하다.
p = malloc(100);
free(p);
q = malloc(100);
이 경우 q는:
새로 OS에서 받은 게 아니라, 방금 free된 걸 재사용할 가능성이 높다
그래서 malloc/free가 빠르다.
그럼 언제 RSS가 줄어들까
완전히 줄어들지 않는 건 아니다.
1. mmap으로 할당된 경우
큰 메모리는 mmap으로 할당되는 경우가 많다.
이 경우 free하면:
free → munmap → OS 반환
👉 이건 바로 RSS 감소로 이어진다.
2. 힙의 끝 부분인 경우
sbrk 기반 메모리는
힙의 끝(top chunk)일 때만 OS에 반환 가능하다.
즉:
- 중간에 있는 free 메모리 → 반환 불가
- 끝에 있는 메모리 → 조건 맞으면 반환 가능
그래서 대부분의 경우는:
그대로 남는다
여기서 더 헷갈리는 포인트 하나
RSS가 증가했다고 해서 무조건 문제가 있는 건 아니다.
RSS는 두 가지가 섞여 있다
- anonymous memory (malloc, stack 등)
- page cache (파일 캐시)
이 둘은 완전히 다른 성격이다.
anonymous memory
- malloc으로 만든 메모리
- 프로세스 전용
- 우리가 흔히 생각하는 “프로그램 메모리”
page cache
- 파일을 읽을 때 생김
- 커널이 관리
- 여러 프로세스가 공유 가능
👉 중요한 포인트
RSS에는 이 둘이 같이 들어간다
그래서 이런 상황이 가능하다.
- RSS 증가
- 하지만 실제로는 page cache 증가
즉,
메모리 누수가 아닐 수도 있다
그래서 분석할 때는 이렇게 봐야 한다
단순히 RSS만 보면 안 된다.
꼭 같이 봐야 하는 것
- RSS
- anon memory
- file-backed memory (page cache)
그리고 항상 이 질문을 해야 한다.
이 메모리는 누가 쓰고 있는 건가?
- malloc인가?
- 파일 캐시인가?
- mmap인가?
여기까지 정리하면
이제 왜 이런 현상이 생기는지 이해된다.
free했는데 메모리가 안 줄어드는 이유
- OS에 반환이 아니라
- allocator 내부로 돌아가기 때문
RSS가 유지되는 이유
- 물리 메모리에 그대로 남아 있기 때문
실제 문제인지 판단하는 기준
- anon인지
- page cache인지
다음으로 이어지는 질문
여기까지 보면 이런 생각이 든다.
그럼 실제로 메모리를 어떻게 분석해야 할까?
/proc/smaps 같은 건 어떻게 읽어야 할까?
이건 단순 개념이 아니라
실제 운영 환경에서 쓰는 내용이라 다음 글에서 다루는 게 자연스럽다.
한 줄 정리
free는 메모리를 OS에 반환하는 동작이 아니라 allocator 내부로 되돌리는 것이기 때문에, 대부분의 경우 RSS는 줄어들지 않는다.
'프로그래밍공부(Programming Study) > CS-운영체제(OS)' 카테고리의 다른 글
| eBPF로 메모리를 추적하는 방법 (0) | 2026.04.06 |
|---|---|
| /proc/smaps로 메모리를 제대로 분석하는 방법 (0) | 2026.04.05 |
| O(1)인데 왜 느려질까 (메모리 성능의 진짜 문제) (0) | 2026.04.03 |
| malloc은 내부에서 어떻게 메모리를 관리할까 (1) | 2026.04.02 |
| malloc은 실제로 어디서 메모리를 가져올까 (0) | 2026.04.01 |
댓글