가비지 컬렉션 & 메모리 프로파일링
누수를 막아 주는 가비지 컬렉션(GC)과 그 한계, 그리고 누수를 찾아내는 프로파일링 도구를 함께 정리했습니다.
가비지 컬렉션 (Garbage Collection)
비유: 자동 청소부 vs 수동 청소
언어별 메모리 관리 방식:
C/C++ (수동) Python/Java (자동 GC)
개발자가 직접 청소 청소부(GC)가 알아서 청소
malloc() → 할당 new Object() → 할당
...사용... ...사용...
free() → 해제 ✋ // 자동으로 해제됨 🤖
↑
잊으면 누수!GC가 있어도 누수가 생기는 경우
python
# Python에서도 누수 가능한 패턴!
cache = [] # 전역 리스트
def 문제있는함수():
data = [0] * (25 * 1024 * 1024) # 25MB
cache.append(data) # 전역에 추가
# GC가 있어도 cache가 참조 중이라 해제 못 함!
# → 참조가 남아있으면 GC도 수거 불가GC의 한계: 참조(Reference)가 남아있으면 수거 불가 → 이 문서에서 "가비지 컬렉션 개선" 권장사항이 나온 이유
메모리 프로파일링 도구
누수를 찾는 도구들
C/C++ 계열:
┌─────────────┬──────────────────────────────────┐
│ Valgrind │ 메모리 접근 오류, 누수 탐지 │
│ AddressSan │ 컴파일 타임 메모리 오류 탐지 │
└─────────────┴──────────────────────────────────┘
Python 계열:
┌─────────────┬──────────────────────────────────┐
│ tracemalloc│ 메모리 할당 추적 (표준 라이브러리) │
│ memory_prof│ 라인별 메모리 사용량 측정 │
│ objgraph │ 객체 참조 그래프 시각화 │
└─────────────┴──────────────────────────────────┘
# Python 예시
import tracemalloc
tracemalloc.start()
# ... 의심 코드 실행 ...
snapshot = tracemalloc.take_snapshot()
for stat in snapshot.statistics('lineno')[:5]:
print(stat) # 어느 줄에서 얼마나 할당했는지 출력정리
| 구분 | 내용 |
|---|---|
| C/C++ | 개발자가 free() 로 직접 해제, 잊으면 누수 |
| Python/Java | GC가 자동 해제, 단 참조가 남아 있으면 수거 불가 |
| C/C++ 도구 | Valgrind, AddressSan |
| Python 도구 | tracemalloc, memory_prof, objgraph |
출처: Codyssey-B1/B4-2
