메모리 구조 (Memory Structure)
실행 파일은 보조 기억장치(SSD)에 저장되어 있다가 실행을 시키면 IO인터럽트가 발생하며 프로세스 제어 블록(PCB)이 생성되며 RAM에 할당됩니다.
이때, 해당 프로세스의 메모리 영역은 크게 Data영역(공용영역), Code영역, 힙, 스택으로 구성됩니다.
C언어의 메모리 구조
이미지 출처: https://ko.wikipedia.org/wiki/동적_메모리_할당
데이터 영역(BSS, DATA)
전역 변수와 정적 변수가 저장되는 영역입니다.
프로그램 시작시 할당되며, 프로그램 종료시 소멸됩니다.
BSS에는 초기 값이 없는 전역 변수를 할당하며, DATA에는 초기 값이 있는 전역 변수를 할당합니다.
코드 영역(TEXT)
실행할 프로그램 코드(제어문, 함수, 등)가 저장되는 영역으로 TEXT 영역이라고도 합니다.
힙 영역
힙 영역은 “자유 저장소”라고도 불리는 공간에서 런타임 동안 필요한 메모리 공간을 할당하며, 사용자가 직접 관리할 수 있는 영역입니다. (동적 메모리 할당)
힙은 낮은 주소에서 높은 주소로 할당됩니다.
이 힙 영역은 런타임 중에 크기가 변경될 수 있습니다.
동적으로 할당된 메모리 공간은 프로그래머가 명시적으로 해제하지 않는 한 계속 유지됩니다.
이로 인해 메모리 릭(leak)이 발생할 수 있으므로 프로그래머는 메모리 관리에 주의를 기울여야 합니다.
단, 프로세스가 종료되는 시점에는 운영 체제에게 메모리 리소스를 반환해야 합니다.
이에 따라 프로세스가 종료될 때 동적으로 할당된 힙 영역은 자동으로 해제됩니다.
따라서 프로그램 종료시에는 명시적으로 메모리를 해제하지 않아도 메모리 영역이 자동으로 해제됩니다.
스택 영역
스택 영역은 컴파일 타임에 크기가 결정되며, 이 결정된 크기를 넘어서면 스택 오버플로우가 발생합니다.
스택은 메모리의 높은 주소에서 낮은 주소로 할당됩니다.
함수 호출시 지역변수, 매개변수, 반환 주소값 등(스택 프레임)이 저장되고 함수 종료시 소멸됩니다.
오버플로우와 언더플로우
- 스택 오버플로우는 함수 호출과 지역 변수 할당 등으로 인해 스택 메모리가 너무 많이 사용되어 스택 영역의 한계를 넘어서려 할 때 발생합니다. 이럴 때는 프로그램이 비정상적으로 종료될 수 있습니다.
- 스택 언더플로우는 반대로 스택에서 더 이상 꺼낼 데이터가 없는데도 불구하고 데이터를 꺼내려 할 때 발생합니다. 이것은 일반적으로 프로그램의 로직 오류로 인해 발생하는 경우가 많습니다.
힙 영역과 스택 영역은 서로 다른 방향으로 성장합니다. 힙 영역은 낮은 주소에서 높은 주소로, 스택 영역은 높은 주소에서 낮은 주소로 성장합니다.
대개는 이 두 영역 사이에 충분한 공간을 두어 서로의 영역을 침범하지 않게 합니다. 그러나 이 공간이 완전히 소진되었을 때, 즉 스택과 힙이 충돌하는 경우를 스택-힙 충돌이라고 합니다.
이러한 상황에서는 스택 영역이 더 이상 성장하지 못하게 되어 (그래서 스택 영역이 초기에 지정된 크기보다 작아지게 됩니다), 스택에 추가적인 데이터를 넣으려고 하는 경우에도 스택 오버플로우가 발생합니다.