Linear Algebra
🕋

The stack and the heap

프로그램이 사용하는 메모리

일반적으로 프로그램이 사용하는 메모리는 segment라고 불리우는 다른 영역들로 나뉘어 집니다.
text : 컴파일 된 프로그램이 메모리 상에 존재하는 영역입니다.
bss : 0으로 초기화 된 global, static 변수들이 저장되는 영역입니다.
data : 특정 값으로 초기화 된 전역, static 변수들이 저장되는 영역입니다.
heap : 동적할당된 변수가 할당되는 영역입니다.
call stack : 함수의 파라미터, 지역 변수 및 기타 함수와 관련된 정보가 저장되는 영역입니다.

Heap 알아보기

heap segment의 경우 free store라고도 알려져 있다. heap은 동적 메모리 할당에 사용되는 메모리를 추적한다. C++에서는 new, delete 키워드를 통해 사용이 가능하다. 자세한 사항은 지면을 따로 할애에 설명하겠습니다.

heap의 특징

heap에 메모리를 할당하는 것은 비교적 느리며, 할당한 메모리는 특별히 할당 해제가 되거나 응용 프로그램이 종료 될 때까지 할당된 상태를 유지한다. 이 때문에 memory leak이라고 불리우는 현상이 나타나지 않게 관리하는 것이 매우 중요하다. 이렇게 동적으로 할당된 메모리의 경우 포인터를 통해 접근할 수 있으며, 포인터를 역참조해여 접근하는 것은 변수에 직접 접근하는 것보다 느립니다. 하지만, heap은 메모리에서 큰 공간을 차지하기 때문에, 용량이 큰 배열, struct, class를 할당할 수 있습니다.

Call stack 알아보기

call stack은 프로그램이 시작할 때부터 현재 실행지점까지 모든 active function들을 추적하고 함수 parameter와 지역 변수의 할당을 처리합니다. 쉽게 말해 함수 단위로 데이터를 처리한다고 보시면 됩니다!!! 예를 들어, 응용 프로그램을 실행시키면, OS에 의해 call stack에 main() 함수를 push하게 되면서 프로그램이 실행되기 시작합니다. 이후 함수 호출이 발생하면 함수가 call stack에 함수를 push하고 현재 함수가 끝나면 해당 함수가 call stack에서 pop됩니다. 이렇게 stack에 push 또는 pop하는 항목들을 stack frame이라고 합니다. 컴퓨터는 해당 변수를 찾기 위해 top 위치에서 몇 번째 메모리 공간에 접근할지 판단하게 됩니다. stack frame은 하나의 함수 호출과 관련된 모든 데이터를 추적합니다. stack frame이 포함하는 것들은 아래와 같습니다.

Stack Frame이 포함하는 항목들

return address : 호출한 함수가 종료된 후 CPU가 어디로 복귀할 지에 대해 알려주는 다음 명령어 주소
함수의 arguments
지역 변수에 대한 메모리
함수가 반환될 때, 변경되었던 register들이 반환되어야하는데, 이 레지스터의 복사본
레지스터를 사용하지 않는 경우 return value값
Register는 CPU에서 작은 메모리입니다. stack call에서는 stack을 기본 자료구조로 사용하여 작업을 수행하게 되는데 이 때 top 값을 레지스터에 값을 저장하게 됩니다. 이것이 바로 SP(stack pointer)입니다. 이를 통해 현재 call stack의 top이 어디에 있는지를 계속해서 추적할 수 있게 됩니다.

Call Stack 발생 순서 살펴보기

1.
프로그램에서 함수 호출이 발생한다
2.
stack frame이 구성되고, stack에 push 된다.
3.
CPU는 함수의 시작점으로 이동한다.
4.
함수안의 명령어들이 실행된다.
5.
함수가 종료되면, 레지스터가 call stack으로 부터 복원됩니다.
6.
stack frame이 stack에서 pop되고, 모든 지역 변수, parameter 에 대한 메모리가 해제됩니다.
7.
반환 값이 있다면 처리됩니다.
8.
return address로 이동해 실행을 재개합니다.

stack의 특징

stack을 통해 메모리를 할당하는 것은 비교적 빠릅니다. 또한 스택에 할당된 메모리는 stack에 있는동안 유지되고 stack에서 pop될 때 사라지게 됩니다. stack에 할당되는 메모리는 compile을 하면서 알 수 있습니다. 이러한 메모리에 접근하기 위해 우리는 변수를 통해서 직접 접근이 가능합니다. 하지만 이러한 stack은 작기 때문에 일반적으로 stack 공간을 많이 차지하는 작업을 수행하는 것은 바람직 하지 않습니다. 힙에서 말씀드렸던 용량이 큰 배열,클래스 생성과 같은 작업이 있습니다. stack의 모든 메모리가 할당 되었을 때 그거보다 많은 데이터를 넣으려고 하면 메모리의 다른 섹션으로 overflow된다고 말합니다. (일반적으로 stack의 크기는 Windows의 경우 1MB, Unix의 경우, 최대 8MB라고 알려져 있습니다.)

Reference