메모리 구조
📋 문서 버전
이 문서는 5개의 버전이 있습니다. 현재 버전 3을 보고 있습니다.
메모리 구조
개요
메모리 구조(Memory Layout)는 컴퓨터 시스템에서 프로그램이 실행될 때 사용하는 메모리의 조직 방식을 의미합니다. 프로그램이 메모리에 적재되면, 그 프로그램은 여러 영역으로 나뉘어 데이터와 코드를 저장하고 관리합니다. 이 구조는 프로그램의 성능, 보안, 안정성에 직접적인 영향을 미치며, 운영체제와 프로그래밍 언어의 특성에 따라 다르게 구성될 수 있습니다.
특히, 프로세스가 실행 중일 때의 메모리 구조는 일반적으로 코드 영역(Text Segment), 데이터 영역(Data Segment), 힙(Heap), 스택(Stack), 그리고 환경 변수 및 명령줄 인자 영역으로 나뉩니다. 이 문서에서는 이러한 메모리 구조의 각 구성 요소와 그 역할, 특징, 그리고 실제 시스템에서의 동작 방식에 대해 자세히 설명합니다.
메모리 구조의 주요 구성 요소
1. 코드 영역 (Text Segment)
코드 영역은 프로그램의 실행 가능한 명령어(기계어 코드)가 저장되는 영역입니다. 이 영역은 일반적으로 읽기 전용(read-only)이며, 프로그램이 메모리에 적재될 때 운영체제에 의해 설정됩니다. 코드 영역은 여러 프로세스가 동일한 프로그램을 실행할 경우 공유 가능(shared)하도록 설계되어 메모리 사용 효율을 높입니다.
- 특징:
- 실행 가능한 명령어 저장
- 읽기 전용 (쓰기 금지)
- 공유 가능
- 예시:
main()함수, 사용자 정의 함수의 기계어 코드
2. 데이터 영역 (Data Segment)
데이터 영역은 프로그램에서 사용하는 전역 변수와 정적 변수를 저장하는 공간입니다. 이 영역은 다시 두 가지 하위 영역으로 나뉩니다:
2.1. 초기화된 데이터 영역 (Initialized Data Segment, .data)
- 초기값이 지정된 전역 변수와 정적 변수가 저장됩니다.
- 예:
int global_var = 10;
2.2. 초기화되지 않은 데이터 영역 (Uninitialized Data Segment, .bss)
- 초기값이 지정되지 않은 전역/정적 변수가 저장됩니다.
- 프로그램 시작 시 0으로 초기화됩니다.
- 예:
static int buffer[1024];
💡
.bss는 "Block Started by Symbol"의 약자로, 메모리 공간을 미리 확보하지만 초기값이 없어 파일 크기를 줄이는 데 유리합니다.
3. 힙 (Heap)
힙은 동적 메모리 할당(Dynamic Memory Allocation)을 위해 사용되는 영역입니다. 프로그래머가 필요에 따라 malloc(), [calloc](/doc/%EA%B8%B0%EC%88%A0/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/C%EC%96%B8%EC%96%B4/calloc)(), [realloc](/doc/%EA%B8%B0%EC%88%A0/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/C%EC%96%B8%EC%96%B4/realloc)() (C 언어 기준) 등을 통해 메모리를 할당하고, free()를 통해 해제합니다.
- 특징:
- 실행 중에 크기가 변할 수 있음
- 수동 관리 필요 (메모리 누수 위험)
- 할당/해제 속도는 스택보다 느림
- 사용 예시:
int *arr = (int*)malloc(100 * sizeof(int)); // 힙에 배열 할당
힙은 프로그램이 실행되는 동안 점차 증가할 수 있으며, 운영체제가 관리하는 가상 메모리 시스템을 통해 확장됩니다.
4. 스택 (Stack)
스택은 함수 호출 시 지역 변수, 매개변수, 반환 주소 등을 저장하는 LIFO(Last In, First Out) 구조의 메모리 영역입니다. 함수가 호출되면 스택 프레임(Stack Frame)이 생성되고, 함수 종료 시 자동으로 해제됩니다.
- 특징:
- 자동 메모리 관리
- 빠른 접근 속도
- 크기 제한 존재 (스택 오버플로우 위험)
- 스택 프레임 구성 요소:
- 지역 변수
- 함수 매개변수
- 반환 주소
- 이전 스택 포인터 저장
⚠️ 재귀 호출이 깊어지거나 큰 지역 배열을 선언하면 스택 오버플로우(Stack Overflow)가 발생할 수 있습니다.
5. 환경 변수 및 명령줄 인자 영역
프로그램이 시작될 때 전달되는 명령줄 인자(argc, argv)와 환경 변수(envp)는 메모리의 최상단 근처에 저장됩니다. 이 영역은 일반적으로 스택 아래쪽 또는 별도의 영역에 위치하며, 프로그램 실행 초기에 접근됩니다.
- 예:
./myprogram arg1 arg2→argv[0] = "./myprogram",argv[1] = "arg1"
메모리 구조의 시각적 표현
다음은 일반적인 프로세스 메모리 레이아웃의 구조입니다:
높은 주소
+-----------------------+
| 환경 변수, 명령줄 인자 |
+-----------------------+
| 스택 | ← 스택 포인터 감소 방향
| (Stack) |
| |
| ... |
| |
| 힙 | ← 힙 포인터 증가 방향
| (Heap) |
+-----------------------+
| 초기화되지 않은 데이터 (.bss) |
+-----------------------+
| 초기화된 데이터 (.data) |
+-----------------------+
| 코드 영역 (.text) |
+-----------------------+
낮은 주소
🔍 주의: 스택은 일반적으로 높은 주소에서 낮은 주소로 확장되며, 힙은 낮은 주소에서 높은 주소로 확장됩니다. 두 영역이 충돌하면 메모리 부족 오류가 발생합니다.
관련 개념 및 고급 주제
가상 메모리와 메모리 보호
현대 운영체제는 가상 메모리(Virtual Memory) 시스템을 사용하여 각 프로세스에 독립적인 주소 공간을 제공합니다. 이는 프로세스 간 메모리 충돌을 방지하고, 물리 메모리보다 큰 메모리 공간을 사용할 수 있게 해줍니다. 또한, 각 메모리 영역에 접근 권한(읽기, 쓰기, 실행)을 설정함으로써 보안을 강화합니다.
예를 들어, 코드 영역은 실행 가능하지만 쓰기 금지이며, 데이터 영역은 쓰기 가능하지만 실행 금지일 수 있습니다. 이는 DEP(Data Execution Prevention) 기술의 기반입니다.
메모리 누수와 관리
힙 영역은 수동 관리가 필요하므로, 할당된 메모리를 해제하지 않으면 메모리 누수(Memory Leak)가 발생합니다. 장시간 실행되는 프로그램(예: 서버)에서는 이로 인해 성능 저하 또는 충돌이 발생할 수 있습니다. 이를 방지하기 위해 스마트 포인터(예: C++의 std::unique_ptr) 또는 가비지 컬렉션(예: Java, Python) 기술이 사용됩니다.
참고 자료 및 관련 문서
- Operating System Concepts - 메모리 관리 장
- The Linux Programming Interface - 프로세스 메모리 레이아웃 설명
- C 표준 라이브러리: malloc, free
- 관련 문서:
- [[가상 메모리]]
- [[스택 오버플로우]]
- [[힙 메모리 관리]]
- [[프로세스 주소 공간]]
이 문서는 컴퓨터 구조와 운영체제의 핵심 개념인 메모리 구조를 이해하는 데 필요한 기초 지식을 제공합니다. 시스템 프로그래밍, 성능 최적화, 보안 분석 등 다양한 분야에서 이 지식은 필수적입니다.
이 문서는 AI 모델(qwen-3-235b-a22b-instruct-2507)에 의해 생성된 콘텐츠입니다.
주의사항: AI가 생성한 내용은 부정확하거나 편향된 정보를 포함할 수 있습니다. 중요한 결정을 내리기 전에 반드시 신뢰할 수 있는 출처를 통해 정보를 확인하시기 바랍니다.