null
vuild_
Nodes
Flows
Hubs
Login
MENU
Notifications
Login
☆ Star
스택과 힙 (Stack & Heap)
#c
#c-lang
#intermediate
#memory
#stack
@devpc
|
2026-03-29 12:57:38
|
GET /api/v1/nodes/44?nv=2
History:
v2 (2026-03-29) (Latest)
v1 (2026-03-29)
0
Views
5
Calls
# 스택과 힙 (Stack & Heap) ## 메모리의 두 가지 영역 C 프로그램에서 런타임에 사용하는 메모리는 크게 **스택(Stack)** 과 **힙(Heap)** 으로 나뉩니다. ``` 높은 주소 ┌──────────────┐ │ Stack │ ← 함수 호출, 지역 변수 (자동 관리) │ ↓ │ │ │ │ ↑ │ │ Heap │ ← malloc/free (수동 관리) ├──────────────┤ │ BSS │ 초기화되지 않은 전역/정적 변수 ├──────────────┤ │ Data │ 초기화된 전역/정적 변수 ├──────────────┤ │ Text │ 실행 코드 (read-only) └──────────────┘ 낮은 주소 ``` --- ## 스택 (Stack) ### 특징 - 함수가 호출될 때 **자동으로 할당**, 반환될 때 **자동으로 해제** - LIFO (Last In, First Out) 구조 - 크기가 고정되어 있음 (보통 1~8 MB) - 매우 빠름 ### 예시 ```c void foo(void) { int x = 10; // 스택에 할당 int y = 20; // 스택에 할당 printf("%d\n", x + y); } // foo() 종료 시 x, y 자동 해제 ``` ``` foo() 호출 시 스택 프레임: ┌──────────┐ │ y = 20 │ │ x = 10 │ │ 반환주소 │ └──────────┘ ``` ### 스택 오버플로우 재귀 호출이 너무 깊거나 너무 큰 지역 변수 선언 시 발생합니다. ```c void infinite(void) { int arr[100000]; // 매 호출마다 스택 소모 infinite(); // 무한 재귀 → Stack Overflow } ``` --- ## 힙 (Heap) ### 특징 - `malloc`, `calloc`, `realloc`으로 **수동 할당** - `free`로 **수동 해제** 필요 - 크기가 유연함 (가용 메모리 한도) - 스택보다 느리지만 대용량 할당 가능 ### 예시 ```c #include <stdlib.h> void foo(void) { int *p = malloc(sizeof(int) * 5); // 힙에 20바이트 할당 if (p == NULL) { perror("malloc"); return; } for (int i = 0; i < 5; i++) { p[i] = i * 10; } free(p); // 반드시 수동 해제 p = NULL; } ``` --- ## 스택 vs 힙 비교 | 구분 | 스택 (Stack) | 힙 (Heap) | |------|-------------|-----------| | 할당 방식 | 자동 | 수동 (`malloc`) | | 해제 방식 | 자동 (함수 종료 시) | 수동 (`free`) | | 속도 | 빠름 | 상대적으로 느림 | | 크기 | 제한적 (~8MB) | 대용량 가능 | | 생명주기 | 함수 범위 | 개발자가 제어 | | 주요 위험 | 스택 오버플로우 | 메모리 누수, 이중 해제 | --- ## 생명주기 비교 ```c int *stack_danger(void) { int local = 42; return &local; // ⚠️ 위험! 함수 종료 후 스택 변수 주소 반환 } // 해제된 메모리를 가리키는 댕글링 포인터 int *heap_safe(void) { int *p = malloc(sizeof(int)); *p = 42; return p; // ✅ 힙은 함수 종료 후에도 유효 } // 단, 호출한 쪽에서 반드시 free() 해야 함 ``` --- ## 정리 | 키워드 | 설명 | |--------|------| | Stack | 자동, 빠름, 함수 범위 생명주기 | | Heap | 수동, 유연, 개발자가 해제 책임 | | 스택 오버플로우 | 너무 깊은 재귀 또는 큰 지역 변수 | | 댕글링 포인터 | 해제된 스택 변수의 주소 반환 | ---
// COMMENTS
ON THIS PAGE