Quick Comparison
선택의 핵심은 빠르다는 인상이 아니라 데이터 크기와 필요한 수명, 소유권을 호출 흐름으로 표현할 수 있는가입니다.
| 기준 | Stack | Heap |
|---|---|---|
| 기본 수명 | 호출과 scope 흐름 | 명시적 소유자·allocator·GC 정책 |
| 관리 단위 | thread별 stack frame | process에서 사용하는 동적 allocation |
| 크기 | 제한적, 큰 지역 데이터에 부적합 | 더 큰 동적 데이터에 적합하지만 무한하지 않음 |
| 대표 실패 | stack overflow, lifetime 이탈 | leak, fragmentation, use-after-free |
수명 선택
함수 안에서만 필요한 작은 상태는 stack 수명과 잘 맞습니다. 호출이 끝날 때 자동으로 정리되므로 별도 해제 경로가 필요하지 않습니다. 반면 크기가 runtime에 결정되거나 호출 이후에도 살아야 하는 데이터는 heap 또는 별도 arena처럼 더 긴 수명 관리가 필요합니다.
void update() {
int count = 0; // 호출 동안 필요한 상태
std::vector<int> values(1000); // 내부 저장소는 동적으로 관리
}객체 변수 자체와 그 객체가 관리하는 저장소는 다른 위치와 수명을 가질 수 있습니다. vector 객체가 stack에 있어도 내부 원소 저장소는 일반적으로 동적 allocation을 사용합니다.
비용과 실패
stack allocation은 보통 pointer 조정으로 처리되어 빠르지만 크기가 제한되고 깊은 재귀나 큰 frame은 overflow를 만들 수 있습니다. heap은 임의 수명과 크기를 지원하지만 allocator 비용, 단편화, 동기화, 수동 언어의 해제 오류가 생길 수 있습니다.
자동 메모리 관리 언어에서도 heap allocation이 사라지는 것은 아닙니다. collection 압력과 pause, 오래 남은 reference를 함께 관리해야 합니다.
자주 틀리는 점
- stack과 heap을 언어 타입 하나만 보고 확정하지 않습니다. compiler와 runtime이 배치를 최적화할 수 있습니다.
- 큰 배열을 stack으로 옮겨 allocation 비용을 없애려다 stack overflow를 만들지 않습니다.
- heap allocation을 피하는 것 자체보다 수명과 ownership을 명확히 하는 것이 먼저입니다.
- 반환한 pointer나 reference가 함수의 지역 수명을 벗어나지 않는지 확인합니다.
참고 링크
2 sources