메모리 저장 영역
프로그램 메모리 구역
프로그램이 실행되면 메모리는 크게 네 영역으로 나뉨
-
코드 영역(Text Segment)
- 기계어로 번역된 실행 코드가 저장됨
-
데이터 영역(Data Segment)
- 전역 변수, static 변수 등이 저장됨
-
힙 영역(Heap)
- 동적 메모리 할당 시 사용하는 영역
-
스택 영역(Stack)
- 함수 호출 시 생기는 임시 데이터 영역
변수 생성과 메모리 저장 규칙
변수 종류 | 저장 위치 | 특징 |
---|---|---|
지역 변수 | 스택 영역 | 함수 호출 시 생성, 종료 시 소멸 |
매개변수 | 스택 영역 | 함수 호출시 스택에 생성 |
전역 변수 | 데이터 영역 | 프로그램 시작 시 생성, 종료 시 소멸 |
static 지역 변수 | 데이터 영역 | 프로그램 시작 시 생성, 스코프는 지역적 |
동적 할당 변수 | 힙 영역 | 개발자가 명시적으로 할당/해제 |
메모리 배치도
[낮은 주소]
+--------------------+
| 코드 영역
+--------------------+
| 데이터 영역
+--------------------+
| 힙 영역 (위로 성장)
+--------------------+
| 스택 영역 (아래로 성장)
+--------------------+
[높은 주소]
- 힙은 낮은 주소 -> 높은 주소 방향으로 성장
- 스택은 높은 주소 -> 낮은 주소 방향으로 성장
- 두 영역이 만나는 순간 메모리 부족 발생
스택 영역(Stack)
- 함수 호출 시 생성되는 임시 데이터 저장소
- 메모리는 LIFO(Last-In, First-Out) 구조로 관리됨
- 컴파일러가 스택 프레임(Stack Frame) 단위로 자동 관리함
스택 프레임 구성
함수 호출 시 스택에 다음 항목들이 쌓인다.
- 복귀 주소: 호출한 위치로 돌아갈 주소
- 매개변수: 함수로 전달된 인자 값
- 지역 변수: 함수 내부에서 선언된 변수
함수가 끝나면, 스택 프레임 전체가 pop되어 메모리가 복구된다.
특징
-
자동 메모리 관리: 생성/소멸이 함수 호출 흐름에 따라 자동으로 관리됨
-
빠른 접근: CPU 캐시 친화적이며 매우 빠르게 메모리 접근 가능
-
제한된 크기: OS가 스택 크기를 제한함
-
오버플로우 위험: 재귀 호출이나 너무 큰 지역 변수 사용 시 Stack Overflow 발생
호출 스택 변화
void bar(int y) {
int b = y + 1;
}
void foo() {
int a = 5;
bar(a);
}
int main() {
foo();
return 0;
}
힙(Heap)
- 프로그램 실행 도중, 필요에 따라 동적으로 할당받는 메모리 공간
- 개발자가 직접
malloc
,calloc
,realloc
,free
등을 호출하여 관리
특징
- 수명 제어 필요: 할당한 메모리는 직접 해제해야 한다.
- 대규모 데이터 가능: 제한 없이 메모리 요청 가능
- 할당 속도 느림: 내부적으로 free list, 관리 테이블 등을 검색하므로 스택보다 느림
- 단편화(fragmentation): 메모리가 조각나 사용 가능한 공간이 줄어드는 현상이 발생할 수 있음
메모리 할당 함수
함수명 | 설명 |
---|---|
malloc | 지정한 바이트 크기만큼 메모리 블록 할당 |
calloc | 여러 블록을 0으로 초기화하며 할당 |
realloc | 기존 메모리 크기 변경 |
free | 메모리 해제 |
#include <stdib.h>
int main() {
int* arr = (int*)malloc(sizeof(int) * 5); // int 5개 공간 할당
if (arr != NULL) {
arr[0] = 10;
arr[1] = 20;
free(arr); // 사용이 끝나면 반드시 해제
}
return 0;
}
malloc
은 성공하면 시작 주소를 반환하고, 실패하면 NULL
을 반환함