Stack과 Heap
프로그램이 실행 중일 때, 변수는 일반적으로 call stack 혹은 process heap에 저장된다.
함수 호출이 끝난 후에도 계속 남아 있는 메모리를 얻고 싶으면 process heap에서 찾아볼 수 있다. (여기서의 프로세스 힙은 data structure의 a heap과는 다르다.)
process heap은 stack과 마찬가지로 실행 중인 프로그램에 변수를 저장하는 메모리 영역이다. stack과 달리 heap의 메모리는 specific function에 묶여 있지 않다. 즉, 하나의 함수는 힙에 메모리를 할당할 수 있고, 다른 함수가 그 해당 메모리를 안전하게 사용할 수 있다.
이렇듯 일반적으로 stack은 지역 변수에만 접근하지만, heap은 전역적으로 변수에 접근할 수 있다. 그리고 stack 영역은 고정된 영역이지만, heap은 그렇지 않다. heap은 동적 메모리 공간이라고도 한다.예를 들어, 파이썬에서 재귀함수 호출을 일정 횟수 이상하다보면 에러(stack overflow)가 발생하곤 한다. 이는 stack 공간이 고정된 공간이기 때문에 발생하는 문제이다.
heap의 예시로는 C의 malloc 함수가 있다. malloc()은 memory allocate의 약자로, 이 함수가 특정 프로세스가 동작하면 프로그램 안에 별도의 메모리 공간을 따로 만든다. 어떤 코드냐에 따라 필요한 공간의 크기가 불분명하므로 프로세스 내 고정된 공간이 아닌 heap과 같은 동적 메모리 공간에 이 함수가 들어간다. 이렇게 메모리가 heap에 할당됨과 동시에 stack frame에는 그것에 대한 포인터가 저장된다.
stack에 있는 변수들은 함수 호출이 끝나면 지워진다. 반면 heap에 있는 변수들은 자동으로 지워지지 않는다. 이 문제를 해결하기 위해 일부 c언어에서는 수동으로 heap allocate을 해제해야 하지만, java 같은 언어에서는 garbage collector가 자동으로 힙 공간을 차지하고 있는 불필요한 객체들을 삭제해준다. java와 같은 객체지향 프로그램은 더더욱 힙 공간이 가득차서 객체가 더 이상 생성되지 않으면 동작에 문제가 생기기 때문이다.
Stack Allocation
할당은 function call stack에서 발생하므로 stack memory allocation이라고 한다.
할당된 메모리의 크기 정보는 컴파일러가 갖고 있으며, 함수가 호출될 때마다 해당 변수는 stack에서 메모리를 가져온다. 그리고 함수 호출이 끝날 때마다 변수에 대한 메모리 할당이 해제된다. 실행이 끝나는 즉시 할당이 해제되므로 임시 메모리 할당(Temporary memory allocation)이라고도 한다.
그러므로 프로그래머는 스택 변수의 메모리 할당과 할당 해제에 대해 신경 쓸 필요가 없다.
Heap Allocation
프로그래머가 작성한 명령어를 실행하는 동안 메모리가 할당된다. 힙이라는 이름은 힙 데이터 구조와는 관련이 없으며, 프로그래머가 할당 및 할당 해제할 수 있는 메모리 공간 더미이므로 힙이라고 부른다. 객체를 만들 때마다 항상 힙 공간을 생성하고 이러한 객체에 대한 참조 정보는 항상 스택 메모리에 저장된다.
힙 메모리 할당은 스택 메모리 할당보다 안전하지 않다. 이 공간에 저장된 데이터는 모든 스레드에서 엑세스할 수 있기 때문이다. 프로그래머가 이 메모리들을 제대로 처리하지 않으면 메모리 누수(memory leak)가 발생할 수 있다.
참고