컴퓨터 메모리 구조 개요
컴퓨터의 메모리는 여러 영역으로 구성되어 있으며, 프로그램이 실행될 때 각 영역이 특정한 역할을 담당합니다. 일반적으로 프로그램이 사용하는 메모리 구조는 다음과 같이 나뉩니다.
1. 프로그램 메모리 구조 (프로세스 메모리 레이아웃)
운영체제(OS)는 실행 중인 프로그램(프로세스)마다 독립적인 가상 메모리 공간을 제공합니다. 메모리는 크게 다음과 같은 5가지 주요 영역으로 나뉩니다.
| 영역 | 설명 |
|---|
| 코드(Code) 영역 | 실행할 프로그램의 명령어(기계어 코드) 저장 |
| 데이터(Data) 영역 | 전역 변수, static 변수 등이 저장 |
| 힙(Heap) 영역 | 동적 할당 메모리 (malloc, new 등) |
| 스택(Stack) 영역 | 함수 호출, 지역 변수, 리턴 주소 등 저장 |
| 커널 영역(Kernel Space) | OS에서 사용하는 영역 (사용자 접근 불가) |
2. 메모리 영역 상세 설명
1) 코드(Code) 영역
- 프로그램 실행 시 읽기 전용으로 로드됨.
- CPU가 실행할 기계어 코드가 저장됨.
.text 섹션에 해당하며, 일반적으로 변경할 수 없음.
1
| int add(int a, int b) { return a + b; }
|
2) 데이터(Data) 영역
- 프로그램 시작부터 종료까지 유지되는 변수 저장.
- 전역 변수 및
static 변수 저장. - 초기화 여부에 따라 두 영역으로 구분됨:
.data (초기화된 전역/정적 변수).bss (초기화되지 않은 전역/정적 변수)
1
2
| int globalVar = 100; // .data 영역
static int staticVar; // .bss 영역
|
3) 힙(Heap) 영역
- 동적 할당된 메모리 (
malloc, new 등) - 필요에 따라 크기가 변하며, 프로그래머가 직접 관리해야 함.
- 메모리 누수(memory leak) 주의 필요.
1
2
| int* p = new int(10); // 힙에 할당됨
delete p; // 할당 해제
|
4) 스택(Stack) 영역
- 함수 호출 시 자동으로 할당되는 영역.
- 지역 변수, 함수 호출 시 전달되는 인자, 리턴 주소 등이 저장됨.
- 함수가 종료되면 스택에서 자동으로 제거됨.
- 스택 크기를 초과하면 스택 오버플로(Stack Overflow) 발생.
1
2
3
| void func() {
int localVar = 10; // 스택에 저장됨
}
|
5) 커널(Kernel) 영역
- OS가 사용하는 특수한 메모리 영역.
- 사용자가 직접 접근할 수 없음.
- 커널 모드에서만 접근 가능.
3. 전체적인 메모리 구조 (주소 배치)
일반적인 메모리 주소 배치 (가상 메모리 기준)
1
2
3
4
5
6
7
8
9
10
11
| --------------------------- (높은 주소)
커널 영역 (OS 코드 및 데이터)
---------------------------
스택 (Stack) ⬇️ (위에서 아래로 성장)
---------------------------
힙 (Heap) ⬆️ (아래에서 위로 성장)
---------------------------
데이터 영역 (.data, .bss)
---------------------------
코드 영역 (.text)
--------------------------- (낮은 주소)
|
- 스택은 높은 메모리 주소에서 아래 방향으로 자람.
- 힙은 낮은 메모리 주소에서 위 방향으로 자람.
4. 물리 메모리 vs 가상 메모리
물리 메모리 (Physical Memory)
- 실제 RAM에 존재하는 메모리.
- 프로세스 간 직접 공유되지 않음.
가상 메모리 (Virtual Memory)
- 프로세스마다 독립적인 메모리 공간을 가짐.
- 운영체제가 가상 주소를 페이지 테이블(Page Table)을 통해 물리 주소로 변환.
- 필요 없는 메모리는 디스크(페이지 파일)로 스왑됨.
5. 메모리 구조와 관련된 문제
1) 스택 오버플로(Stack Overflow)
1
2
3
| void recursive() {
recursive(); // 무한 호출 -> Stack Overflow 발생
}
|
2) 메모리 누수 (Memory Leak)
- 동적 할당(
new, malloc)한 후 해제(delete, free)하지 않으면 발생.
1
2
| int* p = new int[100]; // 동적 할당
// delete[] p; // 해제하지 않으면 메모리 누수 발생
|
3) 댕글링 포인터 (Dangling Pointer)
1
2
3
| int* p = new int(10);
delete p; // 메모리 해제
*p = 20; // 잘못된 접근 (댕글링 포인터)
|
6. 결론
- 프로그램의 메모리는 코드, 데이터, 힙, 스택 영역으로 나뉨.
- 힙과 스택은 서로 반대 방향으로 성장.
- 운영체제는 가상 메모리를 사용하여 효율적으로 메모리를 관리.
- 스택 오버플로, 메모리 누수, 댕글링 포인터와 같은 문제를 주의해야 함.