C/C++의 메모리 관리 문제
C/C++ 프로그램 메모리 영역
C/C++ 프로그램이 실행될 때 메모리 구조는 다음과 같다.
┌─────────────────────────────────────────────────────────────┐
│ 프로세스 메모리 구조 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 높은 주소 ┌─────────────────────────────┐ │
│ │ Stack │ ← 지역변수, 함수호출│
│ │ (자동 할당/해제) │ 컴파일러가 관리 │
│ ├─────────────────────────────┤ │
│ │ ↓ │ │
│ │ (빈 공간) │ │
│ │ ↑ │ │
│ ├─────────────────────────────┤ │
│ │ Heap │ ← malloc/free │
│ │ (동적 할당) │ 개발자가 관리! │
│ ├─────────────────────────────┤ │
│ │ BSS │ ← 초기화 안된 전역│
│ ├─────────────────────────────┤ │
│ │ Data │ ← 초기화된 전역 │
│ ├─────────────────────────────┤ │
│ 낮은 주소 │ Text (Code) │ ← 실행 코드 │
│ └─────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
- 여기서 핵심 문제는 Heap 영역이다.
- Stack: 함수 끝나면 자동 해제
- Data/BSS: 프로그램 종료시 자동 해제
- Heap: 개발자가 직접 해제해야 함
두 가지 메모리 문제
| 문제 | 설명 | 예시 |
| Memory Leak | 할당 후 해제하지 않음 | malloc() 후 free() 안함 |
| Memory Corruption | 잘못된 메모리 접근 | 해제된 메모리 접근, 버퍼 오버플로우 |
// Memory Leak 예시
void memory_leak_example() {
int *ptr = malloc(sizeof(int) * 100);
// ... 사용 ...
// free(ptr); ← 이걸 안하면 누수!
return; // ptr이 가리키는 메모리는 영원히 해제 안됨
}
// Memory Corruption 예시
void memory_corruption_example() {
int *ptr = malloc(sizeof(int));
free(ptr);
*ptr = 10; // 이미 해제된 메모리 접근! (Dangling Pointer)
}
Java vs C/C++ 차이점
Java의 경우
- 물리 메모리 직접 접근 불가
- JVM이 모든 메모리 관리
- GC가 자동으로 미사용 객체 해제
C/C++의 경우
- 포인터로 메모리 직접 접근
- 개발자가 malloc/free 직접 관리
- 실수하면 Leak 또는 Corruption
일반적인 메모리 할당 흐름
┌─────────────────────────────────────────────────────────────┐
│ Normal Scenario │
└─────────────────────────────────────────────────────────────┘
┌─────────────┐ ┌─────────────┐
│ C │ │ Kernel/ │
│ Application │ │ OS │
└─────────────┘ └─────────────┘
│ │
│ ① malloc(100) 호출 │
│ "100바이트 메모리 주세요" │
│ ─────────────────────────────────→ │
│ │
│ ② OS가 메모리 할당
│ (힙 영역에서)
│ │
│ ③ 메모리 주소 반환 │
│ (예: 0x7fff1234) │
│ ←───────────────────────────────── │
│ │
▼ │
ptr = 0x7fff1234 │
사용 후 free(ptr) 해야 함 │
MLD가 포함된 메모리 할당 흐름
┌─────────────────────────────────────────────────────────────┐
│ Our Project - MLD Library 포함 │
└─────────────────────────────────────────────────────────────┘
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ C │ │ MLD │ │ Kernel/ │
│ Application │ │ Library │ │ OS │
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
│ ① xcalloc 호출 │ │
│ "emp_t 1개 주세요" │ │
│ ─────────────────→ │ │
│ │ │
│ │ ② malloc 전달 │
│ │ ─────────────────→ │
│ │ │
│ │ ③ 메모리 주소 반환 │
│ │ ←───────────────── │
│ │ │
│ │ ④ 내부 DB 업데이트 │
│ │ ┌───────────────┐ │
│ │ │ Object DB에 │ │
│ │ │ 기록: │ │
│ │ │ - 주소 │ │
│ │ │ - 타입(emp_t) │ │
│ │ │ - 크기 │ │
│ │ └───────────────┘ │
│ │ │
│ ⑤ 메모리 주소 반환 │ │
│ ←───────────────── │ │
│ │ │
▼ │ │
emp = 0x7fff1234 │ │
(MLD가 추적 중!) │ │