[면접] [CS] 메모리 구조와 Heap(힙), Stack(스택) 메모리 차이
컴퓨터에서 프로그램이 실행되기 위해서는 OS가 프로그램을 메모리에 Load하는 과정이 필요합니다.
메모리는 어떻게 세분화 되어 구분되어 있는지 알아보도록 하겠습니다.
기본적으로 다음과 같이 크게 4가지로 나뉘게 됩니다.
High Address
Stack |
Heap |
Data |
Code |
Low Address
1. Code
1. 코드영역은 실행할 프로그램의 기계어 코드가 저장된 영역입니다.
2. 실행시 ROM(Read - Only - Memory)의 속성을 가집니다.
3. CPU는 Program Counter(PC, 명령어 포인터) 를 통해 이 영역의 명령을 하나씩 실행합니다.
- Q: 코드 영역에서 실행 중인 프로그램이 자기 자신을 수정할 수 있는가?
- A: 일반적으로 불가능하며, 보안상의 이유로 대부분의 OS에서 코드 영역은 읽기 전용으로 설정됨.
2. Data
1. 데이터 영역은 전역 변수와 정적 변수가 저장되는 공간입니다.
2. 세부적으로 초기화된 데이터(.data 섹션) 와 초기화되지 않은 데이터(.bss 섹션) 로 나뉩니다.
2-1. 초기화 된 데이터 (.data섹션)
- 초기값이 있는 전역/정적 변수가 저장됩니다.
- 실행 파일의 .data 섹션에 위치하며, 프로그램이 시작될 때 해당 값으로 초기화됩니다
int global_var = 42; // .data 영역
static int static_var = 100; // .data 영역
2-2. 초기화 되지 않은 데이터 (.bss섹션)
- 초기값이 없는 전역/정적 변수가 저장됩니다.
- 실행 중 자동으로 0으로 초기화됩니다.
- 실제 실행 파일 크기에 영향을 주지 않으며, 실행 중에만 메모리를 차지합니다.
int uninit_global; // .bss 영역
static int uninit_static; // .bss 영역
- Q: 전역 변수와 지역 변수의 차이점은?
- A: 전역 변수는 데이터 영역에 저장되며 프로그램 종료 시까지 유지됨, 지역 변수는 스택 영역에 저장되며 함수 종료 시 소멸됨.
3. Heap
- 동적 메모리 할당(dynamic memory allocation) 이 이루어지는 공간입니다.
- malloc(), calloc(), new 등을 통해 메모리를 할당하며, free() 또는 delete를 통해 해제해야 합니다. Memory Leak방지
- 힙 영역은 프로그램 실행 도중(Run time) 크기가 동적으로 변할 수 있음. - Stack메모리와의 차이점
- 동적 메모리 할당으로 인해 Memory Fragment가 발생 가능 - (OS의 다양한 기법으로 극복)
4. Stack
- 함수 호출시 생성되는 지역변수,매개변수, 함수 호출정보(Stack Frame에 주소로 저장 - return하면 돌아갈 곳) 저장하는 공간
- 공간이 한정되어 있어서 재귀함수등으로 함수를 너무 많이 호출시 Stack Overflow 발생
- 빠른 메모리 접근 속도를 가짐 - 연속된 메모리를 사용해서 분산되어 있는 Heap에 비해서 속도가 빠름
- Compile Time에서 변수의 offset을 complier가 아는것이 가능하기에 스택에서의 위치를 빠르게 찾는것이 가능하다.
- Q: 지역 변수와 전역 변수의 메모리 저장 위치 차이는?
- A: 지역 변수는 스택 영역에 저장되고 함수 종료 시 제거됨, 전역 변수는 데이터 영역에 저장되어 프로그램이 종료될 때까지 유지됨.
void AllocArray(int size)
{
int arr[size];
}
이런식의 할당은 불가능 하다.
AllocArray함수에 들어온 순간 stack에는 size변수가 생성되는데 이는 Compile time이 아닌 Run time에 정해진 것으로 정적배열인 arr에서는 size를 이용해 배열 크기 할당이 불가능하다.
VLA (Variable Length Array)의 형태를 지원하는 compiler에서는 가능할지도 모르지만 (eg. gcc) 일반적으로는 지양된다.
혹은 size변수를 const로 전역선언을 해준다면 Compile time에 크기가 확정되기 때문에 배열 크기로 활용하는 것이 가능하다.
void AllocArray(int size)
{
int* arr = new int[size]; // 동적 메모리 할당
}
이런 방식으로 동적할당을 해준다면 Run time에 동적할당이 가능하다.