프로그램이 실행될 때 운영체제는 프로세스에게 메모리 공간을 할당합니다.
이 메모리 공간은 스택(Stack), 힙(Heap), 데이터(Data), 코드(Code) 영역으로 구분되며, 각 영역의 특성과 동작 방식이 다릅니다.
프로세스 메모리 중 스택 영역은 함수 호출과 지역 변수를 관리합니다.
LIFO (Last-In-First-Out) 구조: 함수 호출 순서대로 쌓이고, 역순으로 해제됩니다.
자동 관리: 함수 호출 시 메모리가 할당되고, 함수 종료 시 자동으로 해제됩니다.
고정된 크기: 대부분의 시스템에서 스택 크기는 제한적입니다 (기본값: 1~8MB).
void recursiveFunc() {
int arr[1000]; // 스택에 1000개의 int 공간 할당 (재귀 시 오버플로우 발생 가능)
recursiveFunc();
}
프로세스 메모리 중 힙 영역은 동적 메모리 할당을 위해 사용됩니다.
특징
수동 관리: 프로그래머가 직접 메모리를 할당(malloc, new)하고 해제(free, delete)해야 합니다.
유연한 크기: 필요에 따라 런타임에 크기가 결정되며, 이론적으로 시스템 메모리 한계까지 확장 가능합니다.
메모리 단편화: 자주 할당/해제하면 메모리 공간이 조각나 효율성이 떨어집니다.
int* arr = malloc(1000 * sizeof(int)); // 힙에 1000개 int 공간 할당
free(arr); // 명시적 해제 필요

운영체제는 각 프로세스에 독립적인 메모리 공간을 할당합니다.
이 공간은 가상 메모리로 관리되며, 스택/힙/데이터/코드 영역으로 분리됩니다.
프로세스 메모리 구조
+-------------------+
| Stack | → 함수 호출, 지역 변수 (자동 확장 ↓)
+-------------------+
| ↓ |
| |
| |
| ↑ |
+-------------------+
| Heap | → 동적 할당 (수동 확장 ↑)
+-------------------+
| Data (전역/static)| → 전역 변수, static 변수
+-------------------+
| Code (텍스트) | → 실행 코드 (읽기 전용)
+-------------------+
스택: 각 스레드마다 별도의 스택이 생성됩니다.
힙: 모든 스레드가 공유합니다 (동기화 필요 🔄).
직접 관리: malloc/free 또는 new/delete 사용.
장점: 성능 최적화 가능.
단점: 메모리 누수 위험 ↑.
가비지 컬렉션(GC): 사용하지 않는 힙 메모리를 자동으로 해제.
장점: 안정성 ↑.
단점: GC 오버헤드로 인한 성능 저하 가능성.
콜 스택: 함수 호출과 지역 변수를 위한 빠르고 자동 관리되는 영역
힙: 동적 메모리를 위한 유연하지만 수동 관리가 필요한 영역
프로세스: 독립적인 메모리 공간을 가지며, 스택/힙은 프로세스 수명 주기와 연결