728x90
Segment
- 메모리 보호를 수행하는 일반적인 방법 가운데 하나
💡 페이징 : 프로세스를 물리적인 단위로 분할하여 메모리에 적재
- 세그먼트 방식은 논리주소를 물리주소로 매핑하는 방식으로 구현한다.
- 세그먼트는 논리적인 단위로 메모리를 로드하기 때문에 메모리 보호가 쉽다.
- 각 세그먼트들의 크기는 균일하지 않다.
- 컴파일러에 의해 자동적으로 프로그램이 로드될 때 세그먼트가 나뉘게 된다.
- 간단히 말해서 메모리에 적재될 때 나뉘는 영역!
Memory Structure
주소 | 영역 | 내용 | 메모리 할당 시기 |
---|---|---|---|
0x0000 (Low Address) |
code(text) | * 코드, 함수, 제어문 등 실행할 프로그램의 코드가 저장되는 영역 | * Compile Time Memory 할당 * 크기 고정 |
data | data | * 초기값이 있는 전역변수, static 변수, 정적 배열, 정적 구조체 등 저장 | |
bss(Block Started by Symbol) | * 전역으로 선언된 초기화 되지 않은 데이터 영역 | ||
heap | * 동적 할당 객체에 대한 영역 * High Address 방향으로 추가 할당 |
* Run Time Memory 할당 * 가변적 크기 |
|
자유영역 | * Heap Overflow : heap 영역이 증가하여 stack 영역을 침범 * Stack Overflow : stack 영역이 증가하여 heap 영역을 침범 |
||
0xFFFF (High Address) |
stack | * 지역변수, 매개변수, 리턴 값 등 임시로 사용하는 것들에 대한 영역 * 매개 변수와 리턴값은 함수 호출 시 생성, 함수 수행 종료시 반환 * Low Address 방향으로 추가 할당 |
Text(Code) Segment
- 코드들이 바이너리화 되어 저장된다.
- 코드만 저장하고 있기 때문에 쓰기가 금지되어있다.
- 텍스트 세그먼트에 쓰려는 시도가 있을 경우, 운영체제가 그 사실을 사용자에게 알리고 프로그램은 종료된다.
- 텍스트 세그먼트가 읽기 전용일 때, 장점으로는 한 종료의 프로그램을 여러 번, 여러 개 실행해도 텍스트 세그먼트를 공유할 수 있다.
- 프로세서가 여기서 명령어를 하나씩 가져와서 실행
- 프로그램이 실행되면 EIP 레지스터의 위치가 텍스트 세그먼트의 맨 처음 위치로 설정된다.
- EIP 레지스터 : 다음에 실행할 명령의 메모리 주소
Data Segment
- 전역변수(global)과 정적변수(static)가 저장되는 메모리 공간
- 해당 공간에 있는 데이터들은 초기값이 있는 전역변수, 배열, static으로 선언된 변수가 들어간다.
- 이 공간은 이후 일정 메모리 접근 공간으로 사용이 가능하다.
- → 프로그램 런타임에 자유롭게 수정 및 변경이 가능하다.
BSS(Block Stated Symbol) Segment
- 전역 / 정적 변수 중 초기화 되지 않은 변수들이 저장되는 공간
- C에서는 초기화되지 않은 정적 변수는 0이나 NULL 로 초기화된다.
- 0과 NULL 모두 컴파일러에서는 모든 비트가 0인 비트패턴으로 표현한다.
- → 해당 작업을 BSS 세그먼트에서 담당한다.
- 컴파일 타임에는 BSS 세그먼트에 할당된 메모리는 메모리만 잡아놓고 초기화시키지 않는다.
→ 어느정도의 공간을 할당할 것이라는 정보만을 저장한다.
- 런타임에 링크되어 올라가고 프로그램을 로드할 때 값이 0으로 초기화된다.
+) 해당 메모리가 필요한 순간까지 OS가 0으로 초기화하는 작업을 지연하는 등 BSS 세그먼트를 효율적으로 구현한다.
- BSS 영역은 어느 정도의 메모리를 확보할 것인지에 대한 정보만 미리 할당해놓고 있다가 런타임 이후에 메모리 영역이 확보된다.
→ 메모리 사용면에서 BSS가 더 효율적이다.
→ 💡 즉, 전역 / 정적 변수 선언시 초기화를 하지 않는 게 더 좋다!
Stack
1. 메모리를 블록처럼 쌓아놓는다.
2. 스택 영역에는 지역변수들과 매개변수 및 리턴주소가 저장된다.
- 매개변수는 레지스터에 저장될 수도 있다.
3. 함수가 선언되면 할당되고, 함수 호출이 종료되면 해제 된다.
- %rsp를 이용한다.
- RSP(Extended Stack Pointer - 스택의 top위치를 가리키는 레지스터
- 할당과 해제를 계속 반복하여, 사이즈가 계속 변한다.
4. stack(지역변수)을 프로그램 하면서 얼마나 사용할 지 미리 계산할 수 없다.
- 메모리의 높은 주소에서 낮은 주소로 할당
5. 4byte 단위로 쪼갠다.
4byte가 안되면 → 2byte → 1byte (32bit 기준)
Heap
- Stack 🆚 Heap
- Stack : 컴파일 타임에 크기 결정
- Heap : 런타임에 동적으로 크기 결정
1. 메모리가 힙 영역에 아무렇게나 할당되어있다.
2. 힙에 저장된 데이터는 함수 호출이 종료되어도 해제되지 않는다.
- 개발자가 명시적으로 해제
- 프로그램 종료
3. 메모리 주소에 따라서 힙 데이터에 접근한다.
4. 힙 공간은 크기의 제약이 없다.
- 메모리가 충분하다면 힙 영역은 필요한만큼 확장될 수 있다.
5. 힙에서 발생되는 메모리 문제
- 사용이 종료된 데이터가 해제되지 않으면 프로그램이 종료될 때까지 메모리 공간을 차지한다.
- 프로그램은 힙에 데이터가 해제되었어도 메모리 주소에 따라서 접근할 수 있다.
- 힙 영역은 크기의 제한은 없지만 가용 메모리가 가득 찰 경우 커널의 OOM Killer에 의해 프로그램이 종료될 수 있다.
6. 메모리의 낮은 주소에서 높은 주소로 할당
7. 사실상 스택과 같은 영역을 공유한다.
- heap과 stack영역의 총합은 정해져있다.
8. 만약 스택과 힙이 겹칠경우, 마지막에 할당한 것에서 이름을 따서 stack overflow, heap overflow가 발생한다.
Memory management functions
- 객체의 타입이 어떤 것 이던지 메모리를 할당할 수 있으며, 할당된 메모리에 대한 포인터 값을 리턴한다.
- 할당이 성공할 경우, 반환되는 포인터는 개체에 대한 접근 또는 어떠한 객체로 이루어진 배열에 대한 접근을 위해 사용한다.
- 공간이 명시적으로 할당 해제될 때까지
- 할당된 개체의 수명은 할당시부터 할당 해제시까지 유지된다.
- 각각의 메모리 영역 할당은 다른 객체의 영역과 분리된다.
- 공간을 할당할 수 없으면 null 포인터가 반환된다.
- 만약 요청되어지는 공간의 크기가 0인 경우에 해당 동작은 구현으로 정의된다.
- null 포인터가 반환되어지거나 크기가 0이 아닌 것 처럼 동작한다.
- But, 반환된 포인터로 개체에 접근하는데 사용되면 안된다.
- 속도 : Stack > Data > Code > Heap
⭐ Summary
- 프로그램을 실행하게 되면 CPU 프로세서는 보조기억장치(HDD, SDD)에 있는 프로그램 정보를 읽어와, RAM메모리(캐시, 주기억장치)에 로드한다.
- 메모리 공간은 프로세스에 할당되어 CPU에 의해 수행된다.
- 이때, 프로그램이 저장되는 메모리 공간은 일반적으로 Code, Data, Stack, Heap의 4가지 세그먼트로 분류된다.
🔗 Reference
- C언어 메모리 관리의 어려움 (1/2) - C언어 메모리 구조
(https://www.kernelpanic.kr/32) - 메모리 영역 (code, data, bss, heap, stack) :: devsin88y
(https://devsin88.tistory.com/100) - 메모리 영역 (Rodata, bss등) :: 마느아의 전산 공부 블로그
(https://learncom1234.tistory.com/80) - line symmetry :: 메모리 영역 (Code, Data, BSS, HEAP, Stack), Little Endian, Stack의 이해
(https://donghwada.tistory.com/entry/메모리-영역-Code-Data-BSS-HEAP-Stack-Little-Endian-Stack의-이해) - C언어 메모리 세그먼트
(https://gusdnd852.tistory.com/16)
728x90
'🌱 Dev Diary > 📄 TIL' 카테고리의 다른 글
Team Session - File Descriptor(FD) (1) | 2022.12.11 |
---|---|
Malloc Lab 구현 (0) | 2022.12.08 |
RB Tree 구현 (0) | 2022.12.06 |
RB Tree 이론 (1) | 2022.11.29 |
C 정복하기(2) - 메모리 할당 (0) | 2022.11.28 |